@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 +15 -0
- package/README.id.md +208 -0
- package/README.md +127 -121
- package/package.json +2 -1
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
|
+
[](https://cahyo-dimas.github.io/freeday-ui-kit/)
|
|
8
|
+
[](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
|
-
|
|
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
|
[](https://cahyo-dimas.github.io/freeday-ui-kit/)
|
|
6
|
-
[](https://github.com/cahyo-dimas/freeday-ui-kit/tree/v1.7.1)
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
**
|
|
10
|
+
A token-driven, framework-agnostic UI kit — one 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
|
-
> 🚀 **
|
|
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;
|
|
17
|
-
# dist/freeday.bundle.css (
|
|
18
|
-
npm 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/`
|
|
22
|
+
`dist/` is committed — consumers don't have to build it themselves.
|
|
21
23
|
|
|
22
|
-
##
|
|
24
|
+
## Use in a project
|
|
23
25
|
|
|
24
|
-
**
|
|
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'; //
|
|
30
|
-
import '@cahyo-dimas/freeday'; //
|
|
31
|
-
// granular
|
|
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
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
> **
|
|
39
|
+
> **From source (no registry):** `npm i github:cahyo-dimas/freeday-ui-kit`.
|
|
38
40
|
|
|
39
|
-
**
|
|
41
|
+
**Or link the files directly (no build):**
|
|
40
42
|
|
|
41
|
-
### 1.
|
|
43
|
+
### 1. Include the CSS (required)
|
|
42
44
|
```html
|
|
43
|
-
<html lang="
|
|
44
|
-
<link rel="stylesheet" href="dist/freeday.tokens.css"> <!--
|
|
45
|
-
<link rel="stylesheet" href="dist/freeday.css"> <!--
|
|
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
|
-
|
|
48
|
-
|
|
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` **
|
|
51
|
-
>
|
|
52
|
-
>
|
|
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.
|
|
55
|
-
|
|
56
|
-
|
|
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)
|
|
60
|
+
<!-- a) one bundle with every enhancer -->
|
|
59
61
|
<script src="dist/freeday.js" defer></script>
|
|
60
62
|
|
|
61
|
-
<!-- b)
|
|
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
|
-
|
|
72
|
+
Each one auto-inits `[data-fdy-*]` on `DOMContentLoaded` — idempotent, progressive enhancement.
|
|
71
73
|
|
|
72
|
-
| Enhancer |
|
|
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
|
-
|
|
89
|
-
`.fdy-table-wrap` (
|
|
90
|
-
(scroll
|
|
91
|
-
border/shadow
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
### 3. Theming — 3
|
|
95
|
-
- `data-theme="light|dark"` —
|
|
96
|
-
- `data-density="comfortable|compact"` —
|
|
97
|
-
|
|
98
|
-
custom/hand-built
|
|
99
|
-
|
|
100
|
-
- (roadmap) `data-style` —
|
|
101
|
-
-
|
|
102
|
-
`src/components/breakpoints.css`)
|
|
103
|
-
'@cahyo-dimas/freeday/breakpoints'` —
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
>
|
|
108
|
-
>
|
|
109
|
-
>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
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); //
|
|
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 |
|
|
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
|
-
|
|
141
|
+
Full library map and patterns: [`docs/integrations.md`](docs/integrations.md).
|
|
139
142
|
|
|
140
|
-
|
|
141
|
-
- **Reuse enhancer:**
|
|
142
|
-
(
|
|
143
|
-
|
|
144
|
-
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
##
|
|
153
|
+
## Token rules — 3 tiers (don't break them)
|
|
150
154
|
```
|
|
151
|
-
Tier 1 PRIMITIVE ramp
|
|
152
|
-
Tier 2 SEMANTIC
|
|
153
|
-
Tier 3 COMPONENT --fdy-<
|
|
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
|
-
|
|
159
|
+
Components only touch Tier 2/3. Need a new value → compose → extend a modifier → only then create.
|
|
156
160
|
|
|
157
|
-
##
|
|
161
|
+
## Repo structure
|
|
158
162
|
```
|
|
159
|
-
tokens/tokens.json
|
|
160
|
-
tokens/build.mjs generator (Node
|
|
161
|
-
src/base.css reset +
|
|
162
|
-
src/components/*.css
|
|
163
|
-
src/*.js
|
|
164
|
-
dist/
|
|
165
|
-
freeday.tokens.css
|
|
166
|
-
freeday.css
|
|
167
|
-
freeday.js
|
|
168
|
-
freeday-*.js
|
|
169
|
-
docs/index.html
|
|
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
|
-
##
|
|
173
|
-
- **
|
|
174
|
-
radius &
|
|
175
|
-
- **
|
|
176
|
-
**select `fdy-combo`** (APG), **autocomplete**, **cascade select**
|
|
177
|
-
**choose-from-list** (field +
|
|
178
|
-
**file upload** (dropzone +
|
|
179
|
-
**form validation** (Constraint Validation API →
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
- **
|
|
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
|
-
##
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
"
|
|
195
|
-
|
|
196
|
-
##
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
`conic-gradient`, `scroll-snap` —
|
|
200
|
-
`-webkit-backdrop-filter` + `backdrop-filter` (Safari
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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.
|
|
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": {
|