uifolio 0.5.1 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -269
- package/cli/uifolio.mjs +446 -164
- package/package.json +3 -2
- package/src/components/ui/audio-player.tsx +7 -7
- package/src/components/ui/calendar.tsx +5 -5
- package/src/components/ui/color-picker.tsx +17 -17
- package/src/components/ui/command-menu.tsx +5 -5
- package/src/components/ui/file-upload.tsx +11 -11
- package/src/components/ui/icon-picker.tsx +12 -12
- package/src/components/ui/resizable.tsx +1 -1
- package/src/components/ui/rich-text-editor.tsx +17 -18
- package/src/components/ui/stories.tsx +4 -4
- package/src/components/ui/table.tsx +164 -0
- package/src/components/ui/video-player.tsx +49 -49
- package/src/lib/date.ts +30 -30
- package/src/lib/uploader.ts +13 -13
- package/src/lib/use-controllable.ts +9 -9
- package/src/lib/use-hotkeys.ts +1 -1
- package/src/lib/use-theme.ts +2 -2
- package/src/lib/video.ts +12 -12
- package/src/lib/vtt.ts +1 -1
package/README.md
CHANGED
|
@@ -2,311 +2,112 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/uifolio)
|
|
4
4
|
[](https://www.npmjs.com/package/uifolio)
|
|
5
|
-
[](https://www.npmjs.com/package/uifolio)
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
A small, theme-friendly UI registry (components live in the target project, copied and edited) with a shadcn-like CLI (`uifolio add`).
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
Le site de démonstration (Vite, animations, playgrounds) vit dans le dépôt du projet et ne
|
|
11
|
-
fait pas partie du paquet.
|
|
8
|
+
## Using the components in another project (CLI)
|
|
12
9
|
|
|
13
|
-
|
|
10
|
+
Like shadcn: you install the files into **your** project, with their helpers,
|
|
11
|
+
and the alias is rewritten automatically.
|
|
14
12
|
|
|
15
13
|
```bash
|
|
16
|
-
npm
|
|
17
|
-
npm run dev # serveur de démo (http://localhost:5173)
|
|
18
|
-
npm run build # typecheck + build de production
|
|
19
|
-
npm run preview # sert le build
|
|
20
|
-
npm run lint # oxlint
|
|
21
|
-
npm test # tests du CLI (copie, couleur, manifeste npm)
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Routes (hash) :
|
|
25
|
-
|
|
26
|
-
- `#/` — page d'accueil (identité UIFolio)
|
|
27
|
-
- `#/docs` — introduction, installation, thème
|
|
28
|
-
- `#/components` — catalogue documenté
|
|
29
|
-
- `#/components/video` — playground VideoPlayer
|
|
30
|
-
- `#/components/calendar`, `/time`, `/audio`, `/stories`, `/editor`, `/upload`,
|
|
31
|
-
`/shortcuts`, `/panels`, `/choice`, `/color-picker`, `/icon-picker`
|
|
32
|
-
- `#/animations/otp` — démo OTP animée
|
|
33
|
-
- `#/animations/accordeon-horizontal`, `/storytelling`, `/empilement`,
|
|
34
|
-
`/texte-progressif`, `/images-fondues` — animations au scroll et fondus d’images
|
|
35
|
-
|
|
36
|
-
Thème **clair/sombre** : bouton dans le header, choix persisté dans
|
|
37
|
-
`localStorage (uifolio-theme)`, initialisation avant le premier rendu (aucun flash),
|
|
38
|
-
défaut = préférence système.
|
|
39
|
-
|
|
40
|
-
**Personnalisation globale** : le panneau de droite (ou l'accordéon sur mobile)
|
|
41
|
-
règle la couleur `--primary` et l'arrondi `--radius` pour tous les composants.
|
|
42
|
-
Le sélecteur avancé propose saturation/luminosité, teinte, alpha, pipette, canaux
|
|
43
|
-
RGB, presets et formats HEX/RGB/HSL/RGBA. Le choix est persisté dans
|
|
44
|
-
`localStorage (uifolio:design)` et repris dans les commandes CLI copiées
|
|
45
|
-
(`--color`, `--radius`).
|
|
46
|
-
|
|
47
|
-
## Utiliser les composants dans un autre projet (CLI)
|
|
48
|
-
|
|
49
|
-
Comme shadcn : tu installes les fichiers dans **ton** projet, avec leurs helpers,
|
|
50
|
-
et l'alias est réécrit automatiquement.
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
# depuis n'importe quel projet, via le paquet npm
|
|
14
|
+
# from any project, through the npm package
|
|
54
15
|
npx uifolio@latest add calendar --color "#10B981" --radius 6
|
|
55
16
|
pnpm dlx uifolio@latest add video-player otp
|
|
56
17
|
|
|
57
|
-
#
|
|
18
|
+
# from the root of the project that contains UIfolio
|
|
58
19
|
npm run uifolio -- list
|
|
59
|
-
npm run uifolio -- init --cwd ../
|
|
60
|
-
npm run uifolio -- add video-player calendar otp --cwd ../
|
|
20
|
+
npm run uifolio -- init --cwd ../my-project
|
|
21
|
+
npm run uifolio -- add video-player calendar otp --cwd ../my-project
|
|
61
22
|
|
|
62
|
-
#
|
|
63
|
-
node cli/uifolio.mjs add otp --cwd ../
|
|
23
|
+
# or directly, through the « bin »
|
|
24
|
+
node cli/uifolio.mjs add otp --cwd ../my-project
|
|
64
25
|
node cli/uifolio.mjs add file-upload --alias "#lib" --dry-run # simulate
|
|
65
26
|
```
|
|
66
27
|
|
|
67
|
-
|
|
|
28
|
+
| Command | Purpose |
|
|
68
29
|
| --- | --- |
|
|
69
|
-
| `uifolio list` |
|
|
70
|
-
| `uifolio init` |
|
|
71
|
-
| `uifolio add <
|
|
72
|
-
|
|
73
|
-
Options : `--cwd <dir>`, `--dir <chemin>` (défaut `src/components/ui`),
|
|
74
|
-
`--lib <chemin>` (défaut `src/lib`), `--alias <alias>` (défaut `@`),
|
|
75
|
-
`--page <chemin>` (créé s'il n'existe pas), `--interactive` (forcer les questions),
|
|
76
|
-
`--force` (écraser), `--dry-run` (simuler), `--color <hex>` et `--radius <px>`.
|
|
77
|
-
|
|
78
|
-
`add` ne s'arrête pas à la copie : sans `--dir` ni `--page`, la CLI demande
|
|
79
|
-
**dans quel dossier** copier les composants, puis **dans quel fichier** les
|
|
80
|
-
utiliser. La page est créée si elle manque ; si elle existe, l'import et le
|
|
81
|
-
`<Composant />` sont ajoutés dans son JSX (sans doublon). Réponds `-` à la
|
|
82
|
-
seconde question pour installer sans toucher à une page.
|
|
83
|
-
|
|
84
|
-
Les couleurs passent par des **tokens Tailwind CSS 4** : la CLI écrit
|
|
85
|
-
`uifolio-theme.css` (`:root`, `.dark`, puis `@theme inline` qui expose
|
|
86
|
-
`--color-primary`, `--color-muted-foreground`, …) et l'importe automatiquement
|
|
87
|
-
dans le CSS global du projet (celui qui fait `@import 'tailwindcss'`). Les
|
|
88
|
-
composants gardent donc `bg-primary`, `border-primary/50`, `ring-primary/40` :
|
|
89
|
-
aucune couleur en dur, `--color` change `--primary` dans le thème et `--radius`
|
|
90
|
-
y ajoute `--radius`. Sans CSS global Tailwind détecté, le fichier est écrit à la
|
|
91
|
-
racine et l'import à ajouter est affiché.
|
|
92
|
-
|
|
93
|
-
À la fin, la CLI affiche les dépendances npm détectées, par ex. :
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
npm install clsx tailwind-merge lucide-react hls.js
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## Thèmes clair/sombre
|
|
100
|
-
|
|
101
|
-
- Tokens CSS : `:root` (clair) et `.dark` (sombre) dans `src/index.css`,
|
|
102
|
-
branchés à Tailwind via `@theme inline` + `@custom-variant dark`.
|
|
103
|
-
- `useTheme()` (`src/lib/use-theme.ts`) : `{ theme, setTheme, toggle }`,
|
|
104
|
-
persistance `localStorage('uifolio-theme')`.
|
|
105
|
-
- `<ThemeToggle />` (`src/components/theme-toggle.tsx`) : bouton Sun/Moon.
|
|
106
|
-
- Jamais de couleur figée dans les composants : tout passe par
|
|
107
|
-
`background`, `foreground`, `card`, `muted`, `border`, `primary`, `accent`, `ring`.
|
|
108
|
-
|
|
109
|
-
## Upload réel
|
|
110
|
-
|
|
111
|
-
Le `FileUpload` ne connaît pas ton backend : il appelle
|
|
112
|
-
`uploader(file, onProgress) => Promise<url>` et affiche progression, succès et lien
|
|
113
|
-
vers l'URL publique renvoyée.
|
|
30
|
+
| `uifolio list` | the available components |
|
|
31
|
+
| `uifolio init` | writes `uifolio.json` (dir, lib, alias) in the target project |
|
|
32
|
+
| `uifolio add <names...>` | copies the component **+ transitive dependencies** (helpers `@/lib/*`) |
|
|
114
33
|
|
|
115
|
-
|
|
34
|
+
Options: `--cwd <dir>`, `--dir <path>` (default `src/components/ui`), `--lib <path>` (default `src/lib`), `--alias <alias>` (default `@`), `--page <path>` (created if missing), `--interactive` (force the questions), `--force` (overwrite), `--dry-run` (simulate), `--color <hex>` and `--radius <px>`.
|
|
116
35
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
un 4xx ne réessaie pas (refus définitif).
|
|
36
|
+
`add` does not stop at the copy. The components always land in
|
|
37
|
+
`src/components/ui` (override with `--dir`) and the page imports them through
|
|
38
|
+
the `@/` alias. Without `--page`, the CLI asks where to use them:
|
|
121
39
|
|
|
122
|
-
|
|
40
|
+
1. *Do you already have a file ready to receive the component (…component…) (y/N) ?* `yes` → *In which file should the component (…component…) be copied (e.g. src/pages/calendar.tsx) ?*: the import and a ready-to-render example are added without duplication, and the file is created when missing;
|
|
41
|
+
2. `no` → *Would you like to create a new folder and an import file (Y/n) ?* `yes` → *Please specify the new path (e.g. src/pages/calendar.tsx) ?*: the folder and the file are created; `no` → install only, no file is touched.
|
|
123
42
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
renvoie une URL PUT signée **SigV4** (implémentée avec `node:crypto`, aucun SDK)
|
|
129
|
-
et le navigateur envoie directement au bucket.
|
|
43
|
+
The example is a small component (`<CalendarExample />` plus its definition)
|
|
44
|
+
that carries the data and props each component needs (items for `Stories` and
|
|
45
|
+
`CommandMenu`, a source for the players, children for the resizable panels…),
|
|
46
|
+
so the component is visible immediately instead of an empty `<Component />`.
|
|
130
47
|
|
|
131
|
-
|
|
48
|
+
Answering `-` to a path question installs the component without creating or
|
|
49
|
+
modifying any page.
|
|
132
50
|
|
|
133
|
-
|
|
51
|
+
Colors go through **Tailwind CSS 4 tokens**: the CLI writes
|
|
52
|
+
`uifolio-theme.css` (`:root`, `.dark`, then `@theme inline`, which exposes
|
|
53
|
+
`--color-primary`, `--color-muted-foreground`, …) and imports it automatically
|
|
54
|
+
into the project's global CSS (the one with `@import 'tailwindcss'`). The
|
|
55
|
+
components therefore keep `bg-primary`, `border-primary/50`, `ring-primary/40`:
|
|
56
|
+
no hard-coded colors. `--color` changes `--primary` in the theme and `--radius`
|
|
57
|
+
adds `--radius` to it. When no global Tailwind CSS is found, the file is written
|
|
58
|
+
at the root and the import to add is printed.
|
|
134
59
|
|
|
135
|
-
|
|
136
|
-
const upload = createUploader({ signEndpoint: '/api/upload/sign' })
|
|
60
|
+
At the end, the CLI prints the detected npm dependencies, for example:
|
|
137
61
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const form = new FormData()
|
|
141
|
-
form.append('file', file)
|
|
142
|
-
const res = await fetch('/api/ton-endpoint', { method: 'POST', body: form })
|
|
143
|
-
const { url } = await res.json()
|
|
144
|
-
return url
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
<FileUpload accept="image/*" uploader={upload} onChange={setFiles} />
|
|
62
|
+
```bash
|
|
63
|
+
npm install clsx tailwind-merge lucide-react hls.js
|
|
148
64
|
```
|
|
149
65
|
|
|
150
|
-
|
|
66
|
+
### Preview parity
|
|
151
67
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
OTP et signature SigV4 sont maison
|
|
68
|
+
The docs preview and the installed component render identically because the page
|
|
69
|
+
written by the CLI ships a demo of the same shape as the docs. If a component
|
|
70
|
+
needs data to show anything (for example Stories, CommandMenu, FileUpload,
|
|
71
|
+
AudioPlayer, VideoPlayer or the resizable panels), the page is created with that
|
|
72
|
+
data, not an empty instance.
|
|
158
73
|
|
|
159
|
-
|
|
74
|
+
If the docs entry for a component is missing, the detail page does not show a blank
|
|
75
|
+
placeholder. It falls back to the preview as-is (or a minimal coherent state) and
|
|
76
|
+
only marks the installation as complete when that is relevant.
|
|
160
77
|
|
|
161
|
-
|
|
162
|
-
| --- | --- | --- |
|
|
163
|
-
| VideoPlayer | `src/components/ui/video-player.tsx` | URL, File/Blob, qualités, HLS, YouTube/Vimeo, sous-titres VTT, contrôles et lecture |
|
|
164
|
-
| Calendar | `src/components/ui/calendar.tsx` | date simple, plage start–end, saisie manuelle, min/max, jours désactivés |
|
|
165
|
-
| TimePicker | `src/components/ui/time-picker.tsx` | 12/24 h, secondes, pas, saisie et flèches |
|
|
166
|
-
| AudioPlayer | `src/components/ui/audio-player.tsx` | variantes carte/compact, seek, volume, vitesse, égaliseur |
|
|
167
|
-
| Stories | `src/components/ui/stories.tsx` | viewer Instagram : images, vidéos, slides texte, pause, progression |
|
|
168
|
-
| RichTextEditor | `src/components/ui/rich-text-editor.tsx` | WYSIWYG `contentEditable`, toolbar, HTML en sortie |
|
|
169
|
-
| FileUpload | `src/components/ui/file-upload.tsx` | drag & drop, validation, aperçus, progression, URL publique, retrait |
|
|
170
|
-
| CommandMenu | `src/components/ui/command-menu.tsx` | palette Ctrl/⌘ + K, recherche, clavier |
|
|
171
|
-
| ResizablePanels | `src/components/ui/resizable.tsx` | groupes horizontal/vertical, poignées, min-size, clavier |
|
|
172
|
-
| OtpInput | `src/components/ui/otp-input.tsx` | 4 champs, collage, rotate + coche de succès |
|
|
173
|
-
| ColorPicker | `src/components/ui/color-picker.tsx` | panneau avancé, saturation/luminosité, teinte, alpha, pipette, canaux RGB, presets, HEX/RGB/HSL/RGBA |
|
|
78
|
+
## Components
|
|
174
79
|
|
|
175
|
-
|
|
80
|
+
| Component | File | What it handles |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| VideoPlayer | `src/components/ui/video-player.tsx` | URL, File/Blob, qualities, HLS, YouTube/Vimeo, VTT subtitles, controls and playback |
|
|
83
|
+
| Calendar | `src/components/ui/calendar.tsx` | single date, start–end range, manual input, min/max, disabled days |
|
|
84
|
+
| TimePicker | `src/components/ui/time-picker.tsx` | 12/24 h, seconds, step, typing and arrow keys |
|
|
85
|
+
| AudioPlayer | `src/components/ui/audio-player.tsx` | card/compact variants, seek, volume, speed, equalizer |
|
|
86
|
+
| Stories | `src/components/ui/stories.tsx` | Instagram viewer: images, videos, text slides, pause, progress |
|
|
87
|
+
| RichTextEditor | `src/components/ui/rich-text-editor.tsx` | `contentEditable` WYSIWYG, toolbar, HTML output |
|
|
88
|
+
| FileUpload | `src/components/ui/file-upload.tsx` | drag & drop, validation, previews, progress, public URL, removal |
|
|
89
|
+
| CommandMenu | `src/components/ui/command-menu.tsx` | Ctrl/⌘ + K palette, search, keyboard |
|
|
90
|
+
| ResizablePanels | `src/components/ui/resizable.tsx` | horizontal/vertical groups, handles, min-size, keyboard |
|
|
91
|
+
| OtpInput | `src/components/ui/otp-input.tsx` | 4 fields, paste, rotate + success check |
|
|
92
|
+
| ColorPicker | `src/components/ui/color-picker.tsx` | advanced panel, saturation/lightness, hue, alpha, eyedropper, RGB channels, presets, HEX/RGB/HSL/RGBA |
|
|
93
|
+
| Table | `src/components/ui/table.tsx` | typed data table, uniform `px-4` cells and a wider gap before Actions, selection and row actions |
|
|
94
|
+
|
|
95
|
+
Copyable helpers (the CLI follows them automatically): `src/lib/utils.ts`,
|
|
176
96
|
`src/lib/video.ts`, `src/lib/vtt.ts`, `src/lib/date.ts`, `src/lib/uploader.ts`, `src/lib/color.ts`,
|
|
177
97
|
`src/lib/use-theme.ts`, `src/lib/use-hotkeys.ts`, `src/lib/use-reduced-motion.ts`.
|
|
178
98
|
|
|
179
|
-
##
|
|
180
|
-
|
|
181
|
-
```tsx
|
|
182
|
-
<VideoPlayer
|
|
183
|
-
sources={file ?? '/video.mp4'}
|
|
184
|
-
aspectRatio="16/9"
|
|
185
|
-
fit="cover"
|
|
186
|
-
controls="full" // full | minimal | none
|
|
187
|
-
accent="#facc15"
|
|
188
|
-
autoPlay
|
|
189
|
-
muted
|
|
190
|
-
loop
|
|
191
|
-
lazy
|
|
192
|
-
subtitles={[
|
|
193
|
-
{ src: '/fr.vtt', label: 'Français', lang: 'fr', default: true },
|
|
194
|
-
{ src: '/en.vtt', label: 'English', lang: 'en' },
|
|
195
|
-
]}
|
|
196
|
-
subtitleClassName="bottom-20"
|
|
197
|
-
overlay={(state) => <MonBadge playing={state.playing} />}
|
|
198
|
-
/>
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
- Sources : URL directe, `File`/`Blob`, tableau de qualités (`{ src, quality }`), `.m3u8`,
|
|
202
|
-
YouTube et Vimeo.
|
|
203
|
-
- Pour les embeds, l'iframe n'est injectée qu'au clic (façade + miniature) et les contrôles
|
|
204
|
-
natifs sont masqués : la barre du composant pilote le lecteur de la plateforme
|
|
205
|
-
(progression, temps, volume, vitesse, lecture/pause) via `postMessage`.
|
|
206
|
-
- `ref` expose `play`, `pause`, `seek`, `mute`, `setVolume`, `setPlaybackRate`,
|
|
207
|
-
`requestFullscreen`, `getVideo`.
|
|
208
|
-
- La barre de progression et le volume suivent l'arrondi global `--radius` (poignées
|
|
209
|
-
comprises), comme le reste du catalogue.
|
|
210
|
-
- Optimisations : chargement lazy, pause hors écran, `preload` maîtrisé, `hls.js` en chunk séparé,
|
|
211
|
-
object URLs révoquées, changement de qualité sans perdre la position.
|
|
212
|
-
- Sous-titres : parsing VTT tolérant, pistes fichier ou URL, style libre via
|
|
213
|
-
`subtitleClassName`, menu CC.
|
|
214
|
-
|
|
215
|
-
## Calendar / TimePicker
|
|
216
|
-
|
|
217
|
-
```tsx
|
|
218
|
-
const [date, setDate] = useState<CalendarValue>(null)
|
|
219
|
-
<Calendar mode="single" value={date} onChange={setDate} min={min} max={max} />
|
|
220
|
-
<Calendar mode="range" value={range} onChange={setRange} />
|
|
221
|
-
<Calendar disabled={(day) => day.getDay() === 0} />
|
|
222
|
-
|
|
223
|
-
<TimePicker value={time} onChange={setTime} withSeconds step={15} hour12 />
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
La saisie manuelle accepte `jj/mm/aaaa`, `jj-mm-aaaa` et `aaaa-mm-jj`.
|
|
227
|
-
|
|
228
|
-
## Audio / Stories
|
|
229
|
-
|
|
230
|
-
```tsx
|
|
231
|
-
<AudioPlayer src="/audio.wav" title="Titre" cover="/cover.svg" accent="#facc15" />
|
|
232
|
-
<AudioPlayer variant="compact" src="/audio.wav" title="Titre" />
|
|
233
|
-
|
|
234
|
-
<Stories items={stories} open={open} onOpenChange={setOpen} duration={5000} />
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
Une story peut être une image, une vidéo ou un slide texte avec son propre fond et sa durée.
|
|
238
|
-
|
|
239
|
-
## Éditeur / Upload / Raccourcis / Panneaux / OTP
|
|
240
|
-
|
|
241
|
-
```tsx
|
|
242
|
-
<RichTextEditor value={html} onChange={setHtml} toolbar />
|
|
243
|
-
|
|
244
|
-
<FileUpload accept="image/*,video/*" maxFiles={3} uploader={upload} onChange={setFiles} />
|
|
245
|
-
|
|
246
|
-
<CommandMenu items={items} open={open} onOpenChange={setOpen} />
|
|
247
|
-
useHotkeys({ 'mod+k': () => setOpen(true) })
|
|
248
|
-
|
|
249
|
-
<ResizablePanelGroup direction="horizontal">
|
|
250
|
-
<ResizablePanel defaultSize={34} minSize={20}>…</ResizablePanel>
|
|
251
|
-
<ResizableHandle />
|
|
252
|
-
<ResizablePanel defaultSize={66} minSize={25}>…</ResizablePanel>
|
|
253
|
-
</ResizablePanelGroup>
|
|
254
|
-
|
|
255
|
-
<OtpInput length={4} value={code} onChange={setCode} onComplete={valider} />
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
L'OTP aligne de 4 à 8 champs, forme un cercle à la validation puis affiche une coche.
|
|
259
|
-
L'animation respecte `prefers-reduced-motion`.
|
|
260
|
-
|
|
261
|
-
## Animations
|
|
262
|
-
|
|
263
|
-
Chaque animation a sa propre page documentée : `#/animations/otp` pour l'OTP, puis
|
|
264
|
-
`#/animations/accordeon-horizontal` et `#/animations/storytelling` pour les cartes
|
|
265
|
-
horizontales, et `#/animations/empilement` pour les cartes qui s'empilent au scroll avec
|
|
266
|
-
une couleur de texte pilotée par la progression. Les couleurs suivent `--primary`. Le
|
|
267
|
-
nombre de cartes se règle de 4 à 8 directement dans chaque aperçu. Ces démos autonomes ne
|
|
268
|
-
sont pas installables via la CLI.
|
|
269
|
-
|
|
270
|
-
## Publier le paquet
|
|
271
|
-
|
|
272
|
-
Le paquet publié ne contient que la CLI, les composants et les helpers (`files`) : aucune
|
|
273
|
-
dépendance d'exécution, React et Tailwind restent en `devDependencies` pour ne pas les
|
|
274
|
-
installer chez ceux qui lancent `npx uifolio`.
|
|
99
|
+
## Publishing the package
|
|
275
100
|
|
|
276
101
|
```bash
|
|
277
|
-
npm
|
|
278
|
-
npm profile enable-2fa auth-and-writes # npm refuse de publier sans 2FA
|
|
279
|
-
npm publish --otp 123456 # prepublishOnly vérifie cli/uifolio.mjs
|
|
102
|
+
npm publish
|
|
280
103
|
```
|
|
281
104
|
|
|
282
|
-
|
|
283
|
-
progressivement ces jetons pour la publication : la 2FA + `--otp` est la voie sûre.
|
|
284
|
-
|
|
285
|
-
Ensuite `npx uifolio@latest add <composant>` et `pnpm dlx uifolio@latest add <composant>`
|
|
286
|
-
fonctionnent.
|
|
287
|
-
|
|
288
|
-
### Publication automatique (GitHub Actions)
|
|
105
|
+
Automatic publishing is wired in `.github/workflows/publish.yml` and runs on tag push.
|
|
289
106
|
|
|
290
|
-
|
|
291
|
-
correspond à la version de `package.json`, installe avec `npm ci`, lance `oxlint`,
|
|
292
|
-
`npm pack --dry-run` et `npm test`, puis publie via **trusted publishing** (OIDC, aucun
|
|
293
|
-
token stocké). Un second job crée ensuite la **GitHub Release** du tag avec les notes
|
|
294
|
-
générées à partir des commits.
|
|
295
|
-
|
|
296
|
-
```bash
|
|
297
|
-
npm version patch # 0.3.0 → 0.3.1, commit + tag v0.3.1
|
|
298
|
-
git push --follow-tags # déclenche le workflow
|
|
299
|
-
```
|
|
107
|
+
### Automatic publishing (GitHub Actions)
|
|
300
108
|
|
|
301
|
-
|
|
109
|
+
The workflow publishes on tag `v*`. Run `git tag vX.Y.Z && git push --tags` to publish.
|
|
302
110
|
|
|
303
|
-
|
|
304
|
-
2. npmjs.com → `uifolio` → Settings → **Trusted publishing** → GitHub Actions :
|
|
305
|
-
organisation `Barronakn`, dépôt `UIfolio`, workflow `publish.yml`,
|
|
306
|
-
action « npm publish » autorisée ;
|
|
307
|
-
3. une configuration neuve doit réussir sa première publication **sous 2 jours**,
|
|
308
|
-
sinon elle expire et il faut la recréer.
|
|
111
|
+
More info: [README on GitHub](https://github.com/Barronakn/UIfolio#readme).
|
|
309
112
|
|
|
310
|
-
|
|
311
|
-
paquet avec Settings → Publishing access → « Require two-factor authentication and
|
|
312
|
-
disallow tokens ».
|
|
113
|
+
License: [MIT](https://opensource.org/license/mit).
|