@cahyo-dimas/freeday 1.7.0 → 1.7.1

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/CHANGELOG.md CHANGED
@@ -3,6 +3,21 @@
3
3
  Semua perubahan penting dicatat di sini. Format longgar mengikuti
4
4
  [Keep a Changelog](https://keepachangelog.com/); tiap versi = git tag.
5
5
 
6
+ ## [1.7.1] — 2026-07-27
7
+ Docs & distribution patch. **No component/code changes** — `dist/`, `src/`, `adapters/`, and
8
+ `tokens/` are byte-identical to 1.7.0.
9
+
10
+ ### Changed
11
+ - **Distributed on public npm as `@cahyo-dimas/freeday`.** Install with `npm i @cahyo-dimas/freeday`
12
+ — `npm ci` now works in CI without auth or an SSH key (the old `git+https` workaround is gone).
13
+ Releases publish via GitHub Actions **OIDC Trusted Publishing** (no tokens).
14
+ - **Docs are now English-first** — `README.md`, `docs/getting-started.md`, `docs/integrations.md`,
15
+ and the example READMEs. `docs/index.html` stays Indonesian for now.
16
+
17
+ ### Added
18
+ - **`README.id.md`** (Bahasa Indonesia) with a language-toggle row on both READMEs; now shipped in
19
+ the published package.
20
+
6
21
  ## [1.7.0] — 2026-07-24
7
22
  Rilis **1.7 — tree checkbox, form-grid, & tiga section docs full-width**. Non-breaking, aditif.
8
23
 
package/README.id.md ADDED
@@ -0,0 +1,208 @@
1
+ # Freeday
2
+
3
+ [English](README.md) · **Bahasa Indonesia**
4
+
5
+ > **Lebih banyak _free day_ buat dev — UI kit-nya sudah siap pakai.**
6
+
7
+ [![Live docs](https://img.shields.io/badge/docs-live-2050d8?style=flat-square)](https://cahyo-dimas.github.io/freeday-ui-kit/)
8
+ [![Release](https://img.shields.io/badge/release-v1.7.1-0078d4?style=flat-square)](https://github.com/cahyo-dimas/freeday-ui-kit/tree/v1.7.1)
9
+
10
+ UI KIT yang token-driven & framework-agnostic — satu sumber kebenaran untuk warna, tipografi,
11
+ spasi, dan komponen. Blueprint: `docs/superpowers/specs/2026-07-21-freeday-ui-kit-design.md`.
12
+ **Referensi hidup:** **[cahyo-dimas.github.io/freeday-ui-kit](https://cahyo-dimas.github.io/freeday-ui-kit/)** — atau buka `docs/index.html` langsung di browser.
13
+
14
+ > 🚀 **Baru mau pakai di project?** Langkah demi langkah per stack (HTML · Vue · React · Blazor): **[`docs/getting-started.md`](docs/getting-started.md)**.
15
+
16
+ ## Build
17
+ ```bash
18
+ node tokens/build.mjs # tokens.json -> dist/freeday.tokens.css; bundel dist/freeday.css;
19
+ # dist/freeday.bundle.css (token+komponen); salin dist/*.js + dist/freeday.js
20
+ npm test # tes transformasi build + kontras WCAG (node:test)
21
+ ```
22
+ `dist/` di-commit — konsumen tak perlu build sendiri.
23
+
24
+ ## Pakai di project
25
+
26
+ **Sebagai paket (project dengan bundler — Vue/React/Blazor/Vite):**
27
+ ```bash
28
+ npm i @cahyo-dimas/freeday
29
+ ```
30
+ ```js
31
+ import '@cahyo-dimas/freeday/css'; // token + komponen (satu file)
32
+ import '@cahyo-dimas/freeday'; // semua enhancer JS (auto-init [data-fdy-*])
33
+ // granular bila perlu: '@cahyo-dimas/freeday/tokens' · '@cahyo-dimas/freeday/css/components' · '@cahyo-dimas/freeday/enhancers/<nama>'
34
+ ```
35
+ Set tema di root app: `<html data-theme="light" data-density="comfortable">`. `dist/` di-commit &
36
+ ter-publish → install tanpa build step; minify diserahkan ke bundler konsumen. Karena terbit di
37
+ **npm publik**, `npm ci` di CI jalan tanpa auth atau SSH key.
38
+
39
+ > **Dari source (tanpa registry):** `npm i github:cahyo-dimas/freeday-ui-kit`.
40
+
41
+ **Atau link file langsung (tanpa build):**
42
+
43
+ ### 1. Sertakan CSS (wajib)
44
+ ```html
45
+ <html lang="id" data-theme="light" data-density="comfortable">
46
+ <link rel="stylesheet" href="dist/freeday.tokens.css"> <!-- token: warna, spasi, dst -->
47
+ <link rel="stylesheet" href="dist/freeday.css"> <!-- komponen fdy-* -->
48
+ ```
49
+ Kelas komponen berprefix `fdy-` (mis. `fdy-btn`, `fdy-card`, `fdy-badge`). Pakai langsung di
50
+ markup framework apa pun — Vue, React, Blazor, atau HTML polos.
51
+
52
+ > `.fdy-btn` **sudah** tombol primary — tak ada modifier `.fdy-btn--primary` terpisah.
53
+ > Modifier untuk varian lain: `--ghost`, `--danger`, `--text`, `--sm`, `--lg`, `--icon`
54
+ > (lihat `docs/index.html`).
55
+
56
+ ### 2. Sertakan JS enhancer (opsional, 0 dependency)
57
+ Komponen interaktif (dropdown, tabs, tabel, choose-from-list, datepicker, upload, toast) butuh
58
+ JS. Dua cara:
59
+ ```html
60
+ <!-- a) satu bundel semua enhancer -->
61
+ <script src="dist/freeday.js" defer></script>
62
+
63
+ <!-- b) atau pilih per-file yang dipakai saja -->
64
+ <script src="dist/freeday-select.js" defer></script> <!-- [data-fdy-combo] -->
65
+ <script src="dist/freeday-tabs.js" defer></script> <!-- [data-fdy-tabs] -->
66
+ <script src="dist/freeday-table.js" defer></script> <!-- [data-fdy-table] -->
67
+ <script src="dist/freeday-cfl.js" defer></script> <!-- [data-fdy-cfl] + <dialog> -->
68
+ <script src="dist/freeday-datepicker.js" defer></script> <!-- [data-fdy-datepicker] -->
69
+ <script src="dist/freeday-upload.js" defer></script> <!-- [data-fdy-dropzone] -->
70
+ <script src="dist/freeday-toast.js" defer></script> <!-- Freeday.toast({...}) -->
71
+ ```
72
+ Semua auto-init `[data-fdy-*]` saat `DOMContentLoaded` — idempotent, progressive enhancement.
73
+
74
+ | Enhancer | Hook markup | Event / API |
75
+ |---|---|---|
76
+ | `freeday-select` | `[data-fdy-combo]` | `fdy-change` `{value}` · `window.FreedayCombo` |
77
+ | `freeday-tabs` | `[data-fdy-tabs]` | `window.FreedayTabs` |
78
+ | `freeday-table` | `[data-fdy-table]` (+ `[data-fdy-filter]`, `[data-fdy-table-bulk]`) | `fdy-table-change` · `window.FreedayTable` |
79
+ | `freeday-cfl` | `[data-fdy-cfl]` → `<dialog>` | `fdy-cfl-select` `{row}`/`{rows}` · `window.FreedayCfl` |
80
+ | `freeday-datepicker` | `[data-fdy-datepicker]`, `[data-fdy-daterange]` | `fdy-datepicker-change` `{value,date}` · `window.FreedayDatepicker` |
81
+ | `freeday-timepicker` | `[data-fdy-timepicker]` | `fdy-time-select` `{value}` · `window.FreedayTimepicker` |
82
+ | `freeday-datetime` | `[data-fdy-datetimepicker]` | `fdy-datetime-change` `{date,time,value}` · `window.FreedayDatetime` |
83
+ | `freeday-cascade` | `[data-fdy-cascade]` (model `<ul>` bersarang) | `fdy-cascade-change` `{value,path,labels}` · `window.FreedayCascade` |
84
+ | `freeday-mask` | `[data-fdy-mask]`, `[data-fdy-password]` | `fdy-mask` `{value,raw}` · `window.FreedayMask` |
85
+ | `freeday-form` | `[data-fdy-validate]` (form) | `fdy-form-invalid`/`-valid` · `window.FreedayForm` |
86
+ | `freeday-chip` | `[data-fdy-chips]`, `.fdy-chip__remove` | `fdy-chip-change`/`fdy-chip-remove` · `window.FreedayChip` |
87
+ | `freeday-upload` | `[data-fdy-dropzone]` | `fdy-upload-add`/`-remove` · `window.FreedayUpload` |
88
+ | `freeday-toast` | — | `Freeday.toast({variant,title,message,timeout})` |
89
+
90
+ Tabel lebar (banyak kolom) butuh wrapper untuk scroll horizontal: bungkus `.fdy-table` dengan
91
+ `.fdy-table-wrap` (tabel biasa, sudah termasuk shell border + shadow) atau `.fdy-table-scroll`
92
+ (scroll polos tanpa shell — jalan standalone maupun di dalam `.fdy-datatable` yang shell
93
+ border/shadow-nya sudah ada sendiri). Tanpa salah satu wrapper ini, tabel lebar akan overflow
94
+ container-nya, bukan scroll sendiri.
95
+
96
+ ### 3. Theming — 3 sumbu lewat `data-*` di root
97
+ - `data-theme="light|dark"` — redefinisi token semantic (bind ke state tema app-mu).
98
+ - `data-density="comfortable|compact"` — tinggi kontrol (`--control-h`) untuk layar padat data.
99
+ Ini auto-apply hanya ke kontrol bawaan Freeday (button, input, combo, dst); komponen
100
+ custom/hand-built harus baca `--control-h` sendiri (mis. `height: var(--control-h)`) supaya ikut
101
+ menyusut/melebar saat `data-density` berubah.
102
+ - (roadmap) `data-style` — varian visual lain.
103
+ - Skala breakpoint (`sm`/`md`/`lg`/`xl` = 600/960/1280/1920px, sama dengan utilitas
104
+ `src/components/breakpoints.css`) juga tersedia di JS: `import { breakpoints } from
105
+ '@cahyo-dimas/freeday/breakpoints'` — dipakai untuk menyamakan `matchMedia`/`@media` app-mu ke
106
+ skala Freeday.
107
+
108
+ ## Integrasi framework (SPA)
109
+ > **Peta library lengkap:** [`docs/integrations.md`](docs/integrations.md) — tiap area
110
+ > (form/validasi, chart, tabel, tanggal, overlay, dst) dipetakan ke library ekosistem yang biasa
111
+ > dipasang (Zod/Yup, Chart.js, TanStack Table, date-fns, Floating UI, …), plus cara
112
+ > menjembataninya + binding Vue/React/Blazor. Buka saat mulai project baru.
113
+
114
+ **Adapter siap pakai — Vue · React · Blazor.** Semua tipis: enhancer tetap sumber kebenaran,
115
+ adapter hanya hydrate + jembatani event. Tiap punya contoh layar **faktur** yang jalan:
116
+
117
+ ```ts
118
+ // Vue 3 — @cahyo-dimas/freeday/vue
119
+ import { useFreeday } from '@cahyo-dimas/freeday/vue';
120
+ const root = ref<HTMLElement | null>(null);
121
+ useFreeday(root); // @fdy-cascade-change="…" (detail bertipe)
122
+ ```
123
+ ```tsx
124
+ // React — @cahyo-dimas/freeday/react
125
+ import { useFreeday } from '@cahyo-dimas/freeday/react';
126
+ const root = useRef<HTMLDivElement>(null);
127
+ useFreeday(root); // event fdy-* bubbling → listen di root
128
+ ```
129
+ ```csharp
130
+ // Blazor — @cahyo-dimas/freeday/blazor (window.FreedayBlazor via JS interop)
131
+ await JS.InvokeVoidAsync("FreedayBlazor.initAll", _root);
132
+ await JS.InvokeAsync<int>("FreedayBlazor.on", _root, "fdy-cascade-change", _self, nameof(OnCascade));
133
+ ```
134
+
135
+ | Framework | Adapter | Contoh jalan |
136
+ |---|---|---|
137
+ | Vue 3 | `@cahyo-dimas/freeday/vue` | [`examples/vue-faktur/`](examples/vue-faktur/) (`npm install && npm run dev`) |
138
+ | React 19 | `@cahyo-dimas/freeday/react` | [`examples/react-faktur/`](examples/react-faktur/) (`npm install && npm run dev`) |
139
+ | Blazor WASM (.NET 10) | `@cahyo-dimas/freeday/blazor` | [`examples/blazor-faktur/`](examples/blazor-faktur/) (`dotnet run`) |
140
+
141
+ Peta library & pola lengkap: [`docs/integrations.md`](docs/integrations.md).
142
+
143
+ Enhancer auto-init sekali saat load. Untuk DOM yang dirender dinamis (Vue/React/Blazor):
144
+ - **Reuse enhancer:** setelah mount/route change, panggil `window.FreedayTable.initAll(el)` (atau
145
+ `initAll()` global). Aman diulang — tiap init dijaga flag idempotent. Jembatani ke state framework
146
+ lewat event yang dipancarkan (mis. dengarkan `fdy-cfl-select`, `fdy-datepicker-change`).
147
+ - **Atau re-implement:** tulis komponen framework sendiri, pertahankan **markup + kontrak ARIA +
148
+ kelas `fdy-*`** yang sama (lihat `docs/index.html`). Enhancer adalah implementasi rujukan, bukan
149
+ keharusan. Untuk choose-from-list, jadikan komponen terkontrol (`fetchPage` callback + server
150
+ cache), jangan mirror ke store global.
151
+
152
+ ## Aturan token — 3 lapis (jangan dilanggar)
153
+ ```
154
+ Tier 1 PRIMITIVE ramp mentah (--azure-600…) — TAK PERNAH dipakai di komponen
155
+ Tier 2 SEMANTIC peran (--color-primary, --color-surface…) — berubah saat theme & re-brand
156
+ Tier 3 COMPONENT --fdy-<komponen>-<prop> — opsional, override lokal
157
+ ```
158
+ Komponen hanya menyentuh Tier 2/3. Butuh nilai baru → compose → extend modifier → baru create.
159
+
160
+ ## Struktur repo
161
+ ```
162
+ tokens/tokens.json sumber sejati (edit di sini)
163
+ tokens/build.mjs generator (Node murni, 0 dependency)
164
+ src/base.css reset + utilitas
165
+ src/components/*.css satu file per komponen (fdy-*)
166
+ src/*.js enhancer JS opsional (rujukan, vanilla)
167
+ dist/ hasil build (DI-COMMIT):
168
+ freeday.tokens.css token semantic (light/dark/compact)
169
+ freeday.css bundel semua komponen
170
+ freeday.js bundel semua enhancer (satu <script>)
171
+ freeday-*.js enhancer per-file
172
+ docs/index.html referensi hidup / demo-site
173
+ ```
174
+
175
+ ## Inventaris komponen
176
+ - **Fondasi:** warna semantic, tipografi (Sora/IBM Plex Sans/JetBrains Mono), skala spasi 4px,
177
+ radius & elevasi, motion, checklist aksesibilitas.
178
+ - **Aksi & form:** button, input (+error), input-group (mata uang/%/ikon), checkbox/radio/switch,
179
+ **select `fdy-combo`** (APG), **autocomplete**, **cascade select** (hierarki drill-down),
180
+ **choose-from-list** (field + dialog single/multi), **date / time / datetime picker**,
181
+ **file upload** (dropzone + state per-berkas), **password reveal + input mask**,
182
+ **form validation** (Constraint Validation API → error aksesibel).
183
+ - **Data:** table, **data table** (cari · sort · **filter per-kolom** teks/enum/angka · **bulk
184
+ actions** · paginasi · seleksi), states (empty/loading/error).
185
+ - **Feedback:** alert, toast, tooltip. **Navigasi:** tabs, breadcrumb, pagination.
186
+ - **Tampilan:** card, badge, avatar, chip (default/hapus · choice · filter), description-list,
187
+ progress, spinner, skeleton.
188
+ - **Layout:** app shell, accordion (native `<details>`), modal (native `<dialog>`), divider, kbd.
189
+
190
+ ## Aksesibilitas
191
+ Kontras WCAG AA (terang & gelap), diaudit otomatis oleh `test/contrast.test.mjs`: menyelesaikan
192
+ graf token, meng-*composite* fill `-soft` semi-transparan di atas surface-nya, dan menegakkan tiap
193
+ pasangan (teks 4.5:1; border kontrol / ikon 3:1, WCAG 1.4.11). Border kontrol form pakai
194
+ `--color-control-border` (≥3:1); border dekoratif sengaja tetap terang. `:focus-visible` selalu
195
+ terlihat, HTML native dulu sebelum ARIA, komponen interaktif ikut pola WAI-ARIA APG, dan
196
+ `prefers-reduced-motion` dihormati. Status tak hanya lewat warna. Lihat section "Aksesibilitas" di
197
+ `docs/index.html`.
198
+
199
+ ## Dukungan browser
200
+ Butuh browser evergreen, kira-kira 2023+: **Chrome 111 · Safari 16.4 · Firefox 113** (floor
201
+ ditentukan `color-mix()`). Fitur lain: native `<dialog>`/`::backdrop`, `accent-color`, `100dvh`,
202
+ `conic-gradient`, `scroll-snap` — semua ≥ Safari 15.4. Blur backdrop pakai
203
+ `-webkit-backdrop-filter` + `backdrop-filter` (Safari lama tetap jalan, hanya tanpa blur). Belum ada
204
+ CSS build/autoprefixer — dukungan browser lama = tanggung jawab konsumen.
205
+
206
+ ## Lisensi
207
+ [MIT](LICENSE) © 2026 Cahyo D. Kurnianto — bebas dipakai, diubah, dan didistribusikan asal
208
+ menyertakan baris copyright + teks lisensi.
package/README.md CHANGED
@@ -1,64 +1,66 @@
1
1
  # Freeday
2
2
 
3
- > **Lebih banyak _free day_ buat dev — UI kit-nya sudah siap pakai.**
3
+ **English** · [Bahasa Indonesia](README.id.md)
4
+
5
+ > **More free days for devs — the UI kit is ready to use.**
4
6
 
5
7
  [![Live docs](https://img.shields.io/badge/docs-live-2050d8?style=flat-square)](https://cahyo-dimas.github.io/freeday-ui-kit/)
6
- [![Release](https://img.shields.io/badge/release-v1.7.0-0078d4?style=flat-square)](https://github.com/cahyo-dimas/freeday-ui-kit/tree/v1.7.0)
8
+ [![Release](https://img.shields.io/badge/release-v1.7.1-0078d4?style=flat-square)](https://github.com/cahyo-dimas/freeday-ui-kit/tree/v1.7.1)
7
9
 
8
- Token-driven, framework-agnostic UI KITsatu sumber kebenaran untuk warna, tipografi,
9
- spasi, dan komponen. Blueprint: `docs/superpowers/specs/2026-07-21-freeday-ui-kit-design.md`.
10
- **Referensi hidup:** **[cahyo-dimas.github.io/freeday-ui-kit](https://cahyo-dimas.github.io/freeday-ui-kit/)** — atau buka `docs/index.html` langsung di browser.
10
+ A token-driven, framework-agnostic UI kitone source of truth for color, typography,
11
+ spacing, and components. Blueprint: `docs/superpowers/specs/2026-07-21-freeday-ui-kit-design.md`.
12
+ **Living reference:** **[cahyo-dimas.github.io/freeday-ui-kit](https://cahyo-dimas.github.io/freeday-ui-kit/)** — or open `docs/index.html` directly in a browser.
11
13
 
12
- > 🚀 **Baru mau pakai di project?** Langkah demi langkah per stack (HTML · Vue · React · Blazor): **[`docs/getting-started.md`](docs/getting-started.md)**.
14
+ > 🚀 **Starting a project?** Step-by-step per stack (HTML · Vue · React · Blazor): **[`docs/getting-started.md`](docs/getting-started.md)**.
13
15
 
14
16
  ## Build
15
17
  ```bash
16
- node tokens/build.mjs # tokens.json -> dist/freeday.tokens.css; bundel dist/freeday.css;
17
- # dist/freeday.bundle.css (token+komponen); salinan dist/*.js + dist/freeday.js
18
- npm test # test transformasi build + kontras WCAG (node:test)
18
+ node tokens/build.mjs # tokens.json -> dist/freeday.tokens.css; bundles dist/freeday.css;
19
+ # dist/freeday.bundle.css (tokens+components); copies dist/*.js + dist/freeday.js
20
+ npm test # build-transform tests + WCAG contrast (node:test)
19
21
  ```
20
- `dist/` di-commitkonsumen tak wajib build sendiri.
22
+ `dist/` is committed consumers don't have to build it themselves.
21
23
 
22
- ## Pakai di project
24
+ ## Use in a project
23
25
 
24
- **Sebagai paket (project dengan bundler — Vue/React/Blazor/Vite):**
26
+ **As a package (projects with a bundler — Vue/React/Blazor/Vite):**
25
27
  ```bash
26
28
  npm i @cahyo-dimas/freeday
27
29
  ```
28
30
  ```js
29
- import '@cahyo-dimas/freeday/css'; // token + komponen (satu file)
30
- import '@cahyo-dimas/freeday'; // semua enhancer JS (auto-init [data-fdy-*])
31
- // granular bila perlu: '@cahyo-dimas/freeday/tokens' · '@cahyo-dimas/freeday/css/components' · '@cahyo-dimas/freeday/enhancers/<nama>'
31
+ import '@cahyo-dimas/freeday/css'; // tokens + components (single file)
32
+ import '@cahyo-dimas/freeday'; // all JS enhancers (auto-init [data-fdy-*])
33
+ // granular if needed: '@cahyo-dimas/freeday/tokens' · '@cahyo-dimas/freeday/css/components' · '@cahyo-dimas/freeday/enhancers/<name>'
32
34
  ```
33
- Set tema di root app: `<html data-theme="light" data-density="comfortable">`. `dist/` di-commit &
34
- ter-publish install jalan **tanpa build step**; minify diserahkan ke bundler konsumen. Karena
35
- terbit di **npm publik**, `npm ci` di CI jalan tanpa auth/SSH key.
35
+ Set the theme on your app root: `<html data-theme="light" data-density="comfortable">`. `dist/` is
36
+ committed and published, so install needs **no build step**; minification is left to the consumer's
37
+ bundler. Because it's on **public npm**, `npm ci` runs in CI without auth or an SSH key.
36
38
 
37
- > **Dari source (tanpa registry):** `npm i github:cahyo-dimas/freeday-ui-kit`.
39
+ > **From source (no registry):** `npm i github:cahyo-dimas/freeday-ui-kit`.
38
40
 
39
- **Atau link file langsung (tanpa build):**
41
+ **Or link the files directly (no build):**
40
42
 
41
- ### 1. Sertakan CSS (wajib)
43
+ ### 1. Include the CSS (required)
42
44
  ```html
43
- <html lang="id" data-theme="light" data-density="comfortable">
44
- <link rel="stylesheet" href="dist/freeday.tokens.css"> <!-- token: warna, spasi, dst -->
45
- <link rel="stylesheet" href="dist/freeday.css"> <!-- komponen fdy-* -->
45
+ <html lang="en" data-theme="light" data-density="comfortable">
46
+ <link rel="stylesheet" href="dist/freeday.tokens.css"> <!-- tokens: color, spacing, etc. -->
47
+ <link rel="stylesheet" href="dist/freeday.css"> <!-- fdy-* components -->
46
48
  ```
47
- Kelas komponen berprefix `fdy-` (mis. `fdy-btn`, `fdy-card`, `fdy-badge`). Pakai langsung di
48
- markup framework apa pun — Vue, React, Blazor, HTML polos.
49
+ Component classes are prefixed `fdy-` (e.g. `fdy-btn`, `fdy-card`, `fdy-badge`). Use them directly
50
+ in any framework's markup — Vue, React, Blazor, or plain HTML.
49
51
 
50
- > `.fdy-btn` **sudah** tombol primary — tidak ada modifier `.fdy-btn--primary` terpisah.
51
- > Modifier yang tersedia untuk varian lain: `--ghost`, `--danger`, `--text`, `--sm`, `--lg`,
52
- > `--icon` (lihat `docs/index.html`).
52
+ > `.fdy-btn` is **already** the primary button there's no separate `.fdy-btn--primary` modifier.
53
+ > Modifiers for other variants: `--ghost`, `--danger`, `--text`, `--sm`, `--lg`, `--icon`
54
+ > (see `docs/index.html`).
53
55
 
54
- ### 2. Sertakan JS enhancer (opsional, 0 dependency)
55
- Komponen interaktif (dropdown, tabs, tabel, choose-from-list, datepicker, upload, toast)
56
- butuh JS. Dua cara:
56
+ ### 2. Include the JS enhancers (optional, zero dependencies)
57
+ Interactive components (dropdown, tabs, table, choose-from-list, datepicker, upload, toast) need
58
+ JS. Two ways:
57
59
  ```html
58
- <!-- a) satu bundel semua enhancer -->
60
+ <!-- a) one bundle with every enhancer -->
59
61
  <script src="dist/freeday.js" defer></script>
60
62
 
61
- <!-- b) atau pilih per-file yang dipakai saja -->
63
+ <!-- b) or pick only the per-file ones you use -->
62
64
  <script src="dist/freeday-select.js" defer></script> <!-- [data-fdy-combo] -->
63
65
  <script src="dist/freeday-tabs.js" defer></script> <!-- [data-fdy-tabs] -->
64
66
  <script src="dist/freeday-table.js" defer></script> <!-- [data-fdy-table] -->
@@ -67,9 +69,9 @@ butuh JS. Dua cara:
67
69
  <script src="dist/freeday-upload.js" defer></script> <!-- [data-fdy-dropzone] -->
68
70
  <script src="dist/freeday-toast.js" defer></script> <!-- Freeday.toast({...}) -->
69
71
  ```
70
- Semua auto-init `[data-fdy-*]` saat `DOMContentLoaded`, idempotent, dan progressive-enhancement.
72
+ Each one auto-inits `[data-fdy-*]` on `DOMContentLoaded` idempotent, progressive enhancement.
71
73
 
72
- | Enhancer | Hook markup | Event / API |
74
+ | Enhancer | Markup hook | Event / API |
73
75
  |---|---|---|
74
76
  | `freeday-select` | `[data-fdy-combo]` | `fdy-change` `{value}` · `window.FreedayCombo` |
75
77
  | `freeday-tabs` | `[data-fdy-tabs]` | `window.FreedayTabs` |
@@ -85,43 +87,44 @@ Semua auto-init `[data-fdy-*]` saat `DOMContentLoaded`, idempotent, dan progress
85
87
  | `freeday-upload` | `[data-fdy-dropzone]` | `fdy-upload-add`/`-remove` · `window.FreedayUpload` |
86
88
  | `freeday-toast` | — | `Freeday.toast({variant,title,message,timeout})` |
87
89
 
88
- Tabel lebar (banyak kolom) butuh wrapper untuk scroll horizontal: bungkus `.fdy-table` dengan
89
- `.fdy-table-wrap` (tabel biasa, sudah termasuk border+shadow shell) atau `.fdy-table-scroll`
90
- (scroll polos tanpa shell — jalan standalone maupun di dalam `.fdy-datatable` yang shell
91
- border/shadow-nya sudah ada sendiri). Tanpa salah satu
92
- wrapper ini tabel lebar akan overflow container-nya, bukan scroll sendiri.
93
-
94
- ### 3. Theming — 3 sumbu lewat `data-*` di root
95
- - `data-theme="light|dark"` — redefinisi token semantic (bind ke state tema app-mu).
96
- - `data-density="comfortable|compact"` — tinggi kontrol (`--control-h`) untuk layar data-dense.
97
- Ini auto-apply hanya ke kontrol bawaan Freeday (button, input, combo, dst); komponen
98
- custom/hand-built harus baca `--control-h` sendiri (mis. `height:var(--control-h)`) supaya
99
- ikut menyusut/melebar saat `data-density` berubah.
100
- - (roadmap) `data-style` — varian visual lain.
101
- - Breakpoint scale (`sm`/`md`/`lg`/`xl` = 600/960/1280/1920px, sama dengan utilitas
102
- `src/components/breakpoints.css`) juga tersedia di JS: `import { breakpoints } from
103
- '@cahyo-dimas/freeday/breakpoints'` — dipakai untuk menyamakan `matchMedia`/`@media` app-mu ke skala Freeday.
104
-
105
- ## Integrasi framework (SPA)
106
- > **Peta library lengkap:** [`docs/integrations.md`](docs/integrations.md) — tiap area
107
- > (form/validasi, chart, tabel, tanggal, overlay, dst) dipetakan ke library ekosistem yang
108
- > biasa dipasang (Zod/Yup, Chart.js, TanStack Table, date-fns, Floating UI, …) + cara
109
- > menjembataninya + binding Vue/React/Blazor. Buka itu saat mulai project baru.
110
-
111
- **Adapter siap pakai — Vue · React · Blazor.** Semua tipis: enhancer tetap sumber kebenaran,
112
- adapter hanya hydrate + jembatani event. Tiap punya contoh layar **faktur** yang jalan:
90
+ Wide tables (many columns) need a wrapper for horizontal scroll: wrap `.fdy-table` in
91
+ `.fdy-table-wrap` (a standard table, includes the border + shadow shell) or `.fdy-table-scroll`
92
+ (plain scroll, no shell — works standalone or inside `.fdy-datatable`, which already has its own
93
+ border/shadow shell). Without one of these wrappers, a wide table overflows its container instead
94
+ of scrolling.
95
+
96
+ ### 3. Theming — 3 axes via `data-*` on the root
97
+ - `data-theme="light|dark"` — redefines the semantic tokens (bind it to your app's theme state).
98
+ - `data-density="comfortable|compact"` — control height (`--control-h`) for data-dense screens.
99
+ This auto-applies only to Freeday's built-in controls (button, input, combo, etc.);
100
+ custom/hand-built components must read `--control-h` themselves (e.g. `height: var(--control-h)`)
101
+ to shrink or grow when `data-density` changes.
102
+ - (roadmap) `data-style` — alternative visual variants.
103
+ - The breakpoint scale (`sm`/`md`/`lg`/`xl` = 600/960/1280/1920px, matching the
104
+ `src/components/breakpoints.css` utilities) is also available in JS: `import { breakpoints } from
105
+ '@cahyo-dimas/freeday/breakpoints'` — use it to align your app's `matchMedia`/`@media` with
106
+ Freeday's scale.
107
+
108
+ ## Framework integration (SPA)
109
+ > **Full library map:** [`docs/integrations.md`](docs/integrations.md) each area (forms/validation,
110
+ > charts, tables, dates, overlays, etc.) mapped to the ecosystem library you'd normally reach for
111
+ > (Zod/Yup, Chart.js, TanStack Table, date-fns, Floating UI, …), plus how to bridge it and the
112
+ > Vue/React/Blazor bindings. Read it when starting a new project.
113
+
114
+ **Ready-made adapters Vue · React · Blazor.** All thin: the enhancer stays the source of truth;
115
+ the adapter only hydrates and bridges events. Each ships a working **invoice** screen:
113
116
 
114
117
  ```ts
115
118
  // Vue 3 — @cahyo-dimas/freeday/vue
116
119
  import { useFreeday } from '@cahyo-dimas/freeday/vue';
117
120
  const root = ref<HTMLElement | null>(null);
118
- useFreeday(root); // @fdy-cascade-change="…" (detail bertipe)
121
+ useFreeday(root); // @fdy-cascade-change="…" (typed detail)
119
122
  ```
120
123
  ```tsx
121
124
  // React — @cahyo-dimas/freeday/react
122
125
  import { useFreeday } from '@cahyo-dimas/freeday/react';
123
126
  const root = useRef<HTMLDivElement>(null);
124
- useFreeday(root); // event fdy-* bubbling → listen di root
127
+ useFreeday(root); // fdy-* events bubble → listen at the root
125
128
  ```
126
129
  ```csharp
127
130
  // Blazor — @cahyo-dimas/freeday/blazor (window.FreedayBlazor via JS interop)
@@ -129,77 +132,80 @@ await JS.InvokeVoidAsync("FreedayBlazor.initAll", _root);
129
132
  await JS.InvokeAsync<int>("FreedayBlazor.on", _root, "fdy-cascade-change", _self, nameof(OnCascade));
130
133
  ```
131
134
 
132
- | Framework | Adapter | Contoh jalan |
135
+ | Framework | Adapter | Working example |
133
136
  |---|---|---|
134
137
  | Vue 3 | `@cahyo-dimas/freeday/vue` | [`examples/vue-faktur/`](examples/vue-faktur/) (`npm install && npm run dev`) |
135
138
  | React 19 | `@cahyo-dimas/freeday/react` | [`examples/react-faktur/`](examples/react-faktur/) (`npm install && npm run dev`) |
136
139
  | Blazor WASM (.NET 10) | `@cahyo-dimas/freeday/blazor` | [`examples/blazor-faktur/`](examples/blazor-faktur/) (`dotnet run`) |
137
140
 
138
- Peta library & pola lengkap: [`docs/integrations.md`](docs/integrations.md).
141
+ Full library map and patterns: [`docs/integrations.md`](docs/integrations.md).
139
142
 
140
- Secara umum, enhancer meng-auto-init sekali saat load. Untuk DOM yang dirender dinamis (Vue/React/Blazor):
141
- - **Reuse enhancer:** setelah mount/route change, panggil `window.FreedayTable.initAll(el)`
142
- (atau `initAll()` global). Aman diulangtiap init dijaga flag idempotent. Jembatani ke
143
- state framework lewat event yang dipancarkan (mis. dengarkan `fdy-cfl-select`, `fdy-datepicker-change`).
144
- - **Atau re-implement:** tulis komponen framework sendiri, pertahankan **markup + kontrak ARIA
145
- + kelas `fdy-*`** yang sama (lihat `docs/index.html`). Enhancer adalah implementasi rujukan,
146
- bukan keharusan. Untuk choose-from-list, jadikan komponen terkontrol (`fetchPage` callback +
147
- server-cache), jangan mirror ke store global.
143
+ Enhancers auto-init once on load. For DOM rendered dynamically (Vue/React/Blazor):
144
+ - **Reuse the enhancer:** after a mount or route change, call `window.FreedayTable.initAll(el)`
145
+ (or the global `initAll()`). Safe to repeat each init is guarded by an idempotent flag. Bridge
146
+ to framework state through the events it emits (e.g. listen for `fdy-cfl-select`,
147
+ `fdy-datepicker-change`).
148
+ - **Or re-implement:** write your own framework component, keeping the same **markup + ARIA
149
+ contract + `fdy-*` classes** (see `docs/index.html`). The enhancer is the reference
150
+ implementation, not a requirement. For choose-from-list, make it a controlled component
151
+ (`fetchPage` callback + server cache) rather than mirroring into a global store.
148
152
 
149
- ## Aturan token — 3 lapis (jangan dilanggar)
153
+ ## Token rules — 3 tiers (don't break them)
150
154
  ```
151
- Tier 1 PRIMITIVE ramp mentah (--azure-600…) — TAK PERNAH dipakai di komponen
152
- Tier 2 SEMANTIC peran (--color-primary, --color-surface…) — berubah saat theme & re-brand
153
- Tier 3 COMPONENT --fdy-<komp>-<prop> — opsional, override lokal
155
+ Tier 1 PRIMITIVE raw ramp (--azure-600…) — NEVER used in components
156
+ Tier 2 SEMANTIC roles (--color-primary, --color-surface…) — change on theme & re-brand
157
+ Tier 3 COMPONENT --fdy-<component>-<prop> — optional, local override
154
158
  ```
155
- Komponen hanya menyentuh Tier 2/3. Butuh nilai baru → compose → extend modifier → baru create.
159
+ Components only touch Tier 2/3. Need a new value → compose → extend a modifier → only then create.
156
160
 
157
- ## Struktur repo
161
+ ## Repo structure
158
162
  ```
159
- tokens/tokens.json sumber sejati (edit di sini)
160
- tokens/build.mjs generator (Node murni, 0 dependency)
161
- src/base.css reset + utilitas
162
- src/components/*.css satu file per komponen (fdy-*)
163
- src/*.js enhancer JS opsional (rujukan, vanilla)
164
- dist/ hasil build (DI-COMMIT):
165
- freeday.tokens.css token semantic (light/dark/compact)
166
- freeday.css bundel semua komponen
167
- freeday.js bundel semua enhancer (satu <script>)
168
- freeday-*.js enhancer per-file
169
- docs/index.html referensi hidup / demo-site
163
+ tokens/tokens.json source of truth (edit here)
164
+ tokens/build.mjs generator (pure Node, zero dependencies)
165
+ src/base.css reset + utilities
166
+ src/components/*.css one file per component (fdy-*)
167
+ src/*.js optional JS enhancers (reference, vanilla)
168
+ dist/ build output (COMMITTED):
169
+ freeday.tokens.css semantic tokens (light/dark/compact)
170
+ freeday.css bundle of every component
171
+ freeday.js bundle of every enhancer (single <script>)
172
+ freeday-*.js per-file enhancers
173
+ docs/index.html living reference / demo site
170
174
  ```
171
175
 
172
- ## Inventaris komponen
173
- - **Fondasi:** warna semantic, tipografi (Sora/IBM Plex Sans/JetBrains Mono), skala spasi 4px,
174
- radius & elevasi, motion, checklist aksesibilitas.
175
- - **Aksi & form:** button, input (+error), input-group (Rp/%/ikon), checkbox/radio/switch,
176
- **select `fdy-combo`** (APG), **autocomplete**, **cascade select** (hierarki drill-down),
177
- **choose-from-list** (field + dialog single/multi), **date / time / datetime picker**,
178
- **file upload** (dropzone + state per-berkas), **password reveal + input mask**,
179
- **form validation** (Constraint Validation API → error aksesibel).
180
- - **Data:** table, **data table** (cari · sort · **filter per-kolom** teks/enum/angka · **bulk
181
- actions** · paginasi · seleksi), states (empty/loading/error).
182
- - **Feedback:** alert, toast, tooltip. **Navigasi:** tabs, breadcrumb, pagination.
183
- - **Tampilan:** card, badge, avatar, chip (default/hapus · choice · filter), description-list,
176
+ ## Component inventory
177
+ - **Foundation:** semantic colors, typography (Sora/IBM Plex Sans/JetBrains Mono), 4px spacing
178
+ scale, radius & elevation, motion, accessibility checklist.
179
+ - **Actions & forms:** button, input (+error), input-group (currency/%/icon),
180
+ checkbox/radio/switch, **select `fdy-combo`** (APG), **autocomplete**, **cascade select**
181
+ (hierarchical drill-down), **choose-from-list** (field + single/multi dialog),
182
+ **date / time / datetime picker**, **file upload** (dropzone + per-file state),
183
+ **password reveal + input mask**, **form validation** (Constraint Validation API → accessible
184
+ errors).
185
+ - **Data:** table, **data table** (search · sort · **per-column filter** text/enum/number · **bulk
186
+ actions** · pagination · selection), states (empty/loading/error).
187
+ - **Feedback:** alert, toast, tooltip. **Navigation:** tabs, breadcrumb, pagination.
188
+ - **Display:** card, badge, avatar, chip (default/removable · choice · filter), description list,
184
189
  progress, spinner, skeleton.
185
190
  - **Layout:** app shell, accordion (native `<details>`), modal (native `<dialog>`), divider, kbd.
186
191
 
187
- ## Aksesibilitas
188
- Kontras WCAG AA (terang & gelap) diaudit otomatis oleh `test/contrast.test.mjs` yang
189
- menyelesaikan graf token, meng-*composite* fill `-soft` semi-transparan di atas surface-nya,
190
- dan menegakkan tiap pasangan (teks 4.5:1; batas kontrol / ikon 3:1, WCAG 1.4.11). Border kontrol
191
- form pakai `--color-control-border` (≥3:1); border dekoratif sengaja tetap terang.
192
- `:focus-visible` selalu terlihat, HTML native dulu sebelum ARIA, komponen interaktif ikut pola
193
- WAI-ARIA APG, hormati `prefers-reduced-motion`. Status tak hanya lewat warna. Lihat section
194
- "Aksesibilitas" di `docs/index.html`.
195
-
196
- ## Dukungan browser
197
- Butuh browser evergreen ~2023+: **Chrome 111 · Safari 16.4 · Firefox 113** (floor ditentukan
198
- oleh `color-mix()`). Fitur lain: native `<dialog>`/`::backdrop`, `accent-color`, `100dvh`,
199
- `conic-gradient`, `scroll-snap` — semua ≥ Safari 15.4. Blur backdrop pakai
200
- `-webkit-backdrop-filter` + `backdrop-filter` (Safari lama tetap jalan, hanya tanpa blur).
201
- Belum ada CSS build/autoprefixer — dukungan browser lama = tanggung jawab konsumen.
202
-
203
- ## Lisensi
204
- [MIT](LICENSE) © 2026 Cahyo D. Kurnianto — bebas dipakai, diubah, dan didistribusikan asal
205
- menyertakan baris copyright + teks lisensi.
192
+ ## Accessibility
193
+ WCAG AA contrast (light & dark), audited automatically by `test/contrast.test.mjs`: it resolves the
194
+ token graph, composites semi-transparent `-soft` fills over their surface, and enforces every pair
195
+ (text 4.5:1; control borders / icons 3:1, WCAG 1.4.11). Form control borders use
196
+ `--color-control-border` (≥3:1); decorative borders are intentionally lighter. `:focus-visible` is
197
+ always visible, native HTML comes before ARIA, interactive components follow the WAI-ARIA APG
198
+ patterns, and `prefers-reduced-motion` is respected. Status is never conveyed by color alone. See
199
+ the "Accessibility" section in `docs/index.html`.
200
+
201
+ ## Browser support
202
+ Needs an evergreen browser, roughly 2023+: **Chrome 111 · Safari 16.4 · Firefox 113** (the floor is
203
+ set by `color-mix()`). Other features used: native `<dialog>`/`::backdrop`, `accent-color`,
204
+ `100dvh`, `conic-gradient`, `scroll-snap` — all ≥ Safari 15.4. Backdrop blur uses
205
+ `-webkit-backdrop-filter` + `backdrop-filter` (older Safari still works, just without the blur).
206
+ There's no CSS build or autoprefixer step supporting older browsers is the consumer's
207
+ responsibility.
208
+
209
+ ## License
210
+ [MIT](LICENSE) © 2026 Cahyo D. Kurnianto — free to use, modify, and distribute, as long as the
211
+ copyright line and license text are included.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cahyo-dimas/freeday",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "Freeday — token-driven, framework-agnostic UI KIT (design source-of-truth).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,6 +26,7 @@
26
26
  "tokens/tokens.json",
27
27
  "tokens/breakpoints.mjs",
28
28
  "README.md",
29
+ "README.id.md",
29
30
  "CHANGELOG.md"
30
31
  ],
31
32
  "exports": {