4 Commits

16 changed files with 3089 additions and 124 deletions

View File

@@ -0,0 +1,23 @@
---
name: "Merge Request"
about: "Template de MR"
title: "[#NUMERO_TICKET] TITRE TICKET"
ref: "main"
---
| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
| | |
## Description de la PR
## Modification du .env
## Check list
- [ ] Pas de régression
- [ ] TU/TI/TF rédigée
- [ ] TU/TI/TF OK
- [ ] CHANGELOG modifié

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
24.13.1

12
CHANGELOG.md Normal file
View File

@@ -0,0 +1,12 @@
# Changelog
Liste des évolutions de la librairie Malio layer UI
## [0.0.0]
### Parameters
### Added
### Changed
### Fixed

View File

@@ -55,26 +55,34 @@ Prévisualiser le build :
npm run preview
```
### Livraison / publication du layer
### Livraison / publication du layer (CI)
Vérifier le contenu qui sera publié :
La publication est automatique via `.gitea/workflows/release.yml` sur push `main` / `master`.
Le job CI :
1. Installe les dépendances
2. Lance `npm run dev:prepare`
3. Lance `npm run lint`
4. Lance `semantic-release` (version automatique + publish sur Gitea Packages)
Les versions sont calculées via Conventional Commits :
- `fix: ...` -> patch (`1.0.0` -> `1.0.1`)
- `feat: ...` -> minor (`1.0.0` -> `1.1.0`)
- `feat!: ...` ou `BREAKING CHANGE:` -> major (`1.0.0` -> `2.0.0`)
Secrets requis dans le repo Gitea :
- `NPM_TOKEN` : token avec droits publish package
- `RELEASE_TOKEN` : token avec droits write repo (tags/releases)
Commande locale utile avant push :
```bash
npm pack --dry-run
```
Publier sur le registry NPM configuré :
```bash
npm publish
```
Publier explicitement sur un registry Gitea :
```bash
npm publish --registry https://<gitea-host>/api/packages/<owner>/npm/
```
## Tester un composant dans le playground
Le playground étend déjà le layer via `.playground/nuxt.config.ts`.
@@ -117,13 +125,28 @@ npm run dev
## Utiliser ce layer dans un autre projet Nuxt
Installer le package :
### 1) Configurer le `.npmrc` du projet consommateur
Option simple :
```ini
@malio:registry=https://gitea.malio.fr/api/packages/MALIO-DEV/npm/
```
Puis :
```bash
export NPM_TOKEN=TON_TOKEN_GITEA
```
### 2) Installer le package
```bash
npm install @malio/layer-ui
```
Étendre le layer dans `nuxt.config.ts` du projet consommateur :
### 3) Étendre le layer
Dans `nuxt.config.ts` du projet consommateur :
```ts
export default defineNuxtConfig({

View File

@@ -0,0 +1,23 @@
import { describe, expect, it } from 'vitest'
import { mount } from '@vue/test-utils'
import Input from './Input.vue'
describe('MalioInput', () => {
it('affiche la valeur initiale', () => {
const wrapper = mount(Input, {
props: { modelValue: 'hello' },
})
expect(wrapper.get('input').element.value).toBe('hello')
})
it('emet update:modelValue au changement', async () => {
const wrapper = mount(Input, {
props: { modelValue: '' },
})
await wrapper.get('input').setValue('new value')
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['new value'])
})
})

View File

@@ -0,0 +1,56 @@
<template>
<Story title="Input/Text">
<MalioInputText/>
</Story>
</template>
<docs lang="md">
# Input Text
## Liste des props
Le composant Input Text permet de saisir du texte. Il peut afficher des messages d'erreur, de succès ou d'information.
On peut lui passer plusieurs props pour personnaliser son comportement et son apparence.
- id: Identifiant HTML du champ. Si non fourni, un id est généré automatiquement.
- label: Texte du label affiché au-dessus du champ (floating label).
- name: Attribut name de linput.
- autocomplete: Attribut autocomplete de linput.
- modelValue: Valeur du champ (utilisée avec v-model) ou si valeur brut mettre des " ".
- minWidth: Classe utilitaire pour la largeur minimale du conteneur. Classe Tailwind de largeur (ex: w-64, w-full).
- maxWidth: Classe utilitaire pour la largeur maximale du conteneur. Classe Tailwind de largeur maximale.
- textInput: Classe(s) de style du texte de linput. Classe(s) Tailwind de couleur ou de typographie (ex : text-gray-700, text-sm).
- textLabel: Classe(s) de style du texte du label. Classe(s) Tailwind de couleur ou de typographie (ex : text-gray-700, text-sm).
- required: Rend le champ obligatoire (required).
- maxLength: Nombre de caractère maximal autorisé.
- minLength: Nombre de caractère minimal autorisé.
- disabled: Désactive le champ et applique le style désactivé.
- readonly: Met le champ en lecture seule.
- hint: Message informatif affiché sous le champ.
- error: Message derreur affiché sous le champ. Active le style erreur.
- success: Message de succès affiché sous le champ. Active le style succès.
- iconName: Nom de licône affichée à droite dans le champ.
- rounded: Classe utilitaire pour le rayon des coins ( rounded- ).
- iconSize: Taille de licône. (ex : 24, 26, 85 ,99, ... ).
- iconColor: Classe(s) personnalisée(s) de couleur pour licône ( text- ).
- mask: Masque de saisie pour formater la valeur :
- \# : chiffre
- A : lettre majuscule
- a : lettre minuscule
- \* : chiffre ou lettre
Événement émis :
- update:modelValue: Émis à chaque saisie pour mettre à jour v-model.
Règles daffichage des messages :
Priorité daffichage :
1) error
2) success
3) hint
</docs>
<script setup lang="ts">
import MalioInputText from '../components/malio/InputText.vue'
</script>

31
commit-msg Normal file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail
MSG_FILE="${1}"
FIRST_LINE="$(head -n 1 "$MSG_FILE" | tr -d '\r')"
# Autoriser commits auto-générés par git
if [[ "$FIRST_LINE" =~ ^Merge\ ]]; then
exit 0
fi
# Types autorisés (MINUSCULES uniquement)
# Optionnel: scope => feat(auth) : ...
REGEX='^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z0-9._-]+\))?\ :\ .+'
if [[ ! "$FIRST_LINE" =~ $REGEX ]]; then
echo "❌ Message de commit invalide."
echo ""
echo "➡️ Format attendu : <type>(<scope optionnel>) : <message>"
echo "➡️ Types autorisés (minuscules uniquement) :"
echo " build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test"
echo ""
echo "✅ Exemples :"
echo " feat : add login page"
echo " fix(auth) : prevent null token crash"
echo " docs : update README"
echo ""
echo "❌ Exemple refusé :"
echo " Feat : add login page"
exit 1
fi

24
histoire.config.ts Normal file
View File

@@ -0,0 +1,24 @@
import { defineConfig } from 'histoire'
import { HstVue } from '@histoire/plugin-vue'
import vue from '@vitejs/plugin-vue'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
import path from 'path'
export default defineConfig({
setupFile: './histoire.setup.ts',
vite: {
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, './'),
},
},
css: {
postcss: {
plugins: [tailwindcss(), autoprefixer()],
},
},
},
plugins: [HstVue()],
})

4
histoire.setup.ts Normal file
View File

@@ -0,0 +1,4 @@
import './app/assets/css/malio.css'
export function setupVue3() {}
export function setupVanilla() {}

33
makefile Normal file
View File

@@ -0,0 +1,33 @@
.PHONY: start install dev dev-prepare lint test pre-commit copy-git-hook node-use
start: copy-git-hook node-use install
install:
npm install
dev:
npm run dev
dev-histoire:
npm run story:dev
dev-prepare:
npm run dev:prepare
lint: dev-prepare
npm run lint
test:
npm run test
pre-commit: lint test
copy-git-hook:
cp pre-commit .git/hooks/pre-commit
cp commit-msg .git/hooks/commit-msg
chmod a+x .git/hooks/pre-commit
chmod a+x .git/hooks/commit-msg
# Force la version node
node-use:
bash -lc 'source "$$HOME/.nvm/nvm.sh" && nvm install && nvm use'

2839
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,20 +10,32 @@
"build": "nuxt build .playground",
"generate": "nuxt generate .playground",
"preview": "nuxt preview .playground",
"lint": "eslint ."
"lint": "eslint .",
"test": "vitest run",
"story:dev": "histoire dev",
"story:build": "histoire build",
"story:preview": "histoire preview"
},
"peerDependencies": {
"nuxt": "^4.0.0"
},
"devDependencies": {
"@histoire/plugin-vue": "^1.0.0-beta.1",
"@nuxt/eslint": "latest",
"@types/node": "^24.10.13",
"@vitejs/plugin-vue": "^6.0.4",
"@vue/test-utils": "^2.4.6",
"eslint": "^10.0.0",
"histoire": "^1.0.0-beta.1",
"jsdom": "^27.0.1",
"nuxt": "^4.3.1",
"typescript": "^5.9.3",
"vitest": "^3.2.4",
"vue": "latest"
},
"dependencies": {
"@nuxtjs/tailwindcss": "^6.14.0"
"@nuxt/icon": "^2.2.1",
"@nuxtjs/tailwindcss": "^6.14.0",
"maska": "^3.2.0"
}
}

28
pre-commit Normal file
View File

@@ -0,0 +1,28 @@
#!/bin/sh
set -e
echo "######### Pre-commit hook start #############"
# Prefer the exact Node version from .nvmrc for hooks (IDE + CLI consistency).
if [ -f ".nvmrc" ]; then
NVM_VERSION="$(tr -d '\r\n' < .nvmrc)"
NVM_VERSION="${NVM_VERSION#v}"
NVM_BIN="$HOME/.nvm/versions/node/v$NVM_VERSION/bin"
if [ -x "$NVM_BIN/node" ] && [ -x "$NVM_BIN/npm" ]; then
PATH="$NVM_BIN:$PATH"
export PATH
fi
fi
if ! command -v npm >/dev/null 2>&1; then
echo "npm introuvable dans le hook. Abandon du commit."
exit 1
fi
echo "Node $(node -v) / npm $(npm -v)"
echo "--- make pre-commit start ---"
make pre-commit
echo "--- make pre-commit finished ---"
echo "All checks passed. Proceeding with commit."
exit 0

38
tailwind.config.ts Normal file
View File

@@ -0,0 +1,38 @@
import type { Config } from 'tailwindcss'
export default {
content: [
'./app/**/*.{vue,js,ts}',
'./**/*.story.{vue,js,ts}',
'./histoire.setup.ts',
'./histoire.config.ts',
],
safelist: [
{
pattern: /(sm:|md:|lg:|xl:|2xl:)?(text|rounded|w)-.+/,
},
],
theme: {
extend: {
borderRadius: {
malio: 'var(--m-radius)',
},
colors: {
m: {
primary: 'rgb(var(--m-primary) / <alpha-value>)',
secondary: 'rgb(var(--m-secondary) / <alpha-value>)',
tertiary: 'rgb(var(--m-tertiary) / <alpha-value>)',
border: 'rgb(var(--m-border) / <alpha-value>)',
text: 'rgb(var(--m-text) / <alpha-value>)',
muted: 'rgb(var(--m-muted) / <alpha-value>)',
bg: 'rgb(var(--m-bg) / <alpha-value>)',
error: 'rgb(var(--m-error) / <alpha-value>)',
success: 'rgb(var(--m-success) / <alpha-value>)',
},
},
fontFamily: {
sans: ['"Helvetica Neue"', 'Helvetica', 'Arial', 'sans-serif'],
},
},
},
} satisfies Partial<Config>

View File

@@ -1,3 +1,21 @@
{
"extends": "./.playground/.nuxt/tsconfig.json"
"extends": "./.playground/.nuxt/tsconfig.json",
"compilerOptions": {
"target": "es2017",
"module": "esnext",
"lib": [
"esnext"
],
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"strictNullChecks": true,
"resolveJsonModule": true,
"jsx": "preserve"
},
"include": [
"env.d.ts",
"src/**/*",
"src/**/*.vue"
]
}

10
vitest.config.ts Normal file
View File

@@ -0,0 +1,10 @@
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'jsdom',
include: ['app/**/*.test.ts'],
},
})