@cahyo-dimas/freeday 1.18.0 → 1.21.0

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/COMPONENTS.md +775 -0
  3. package/README.id.md +11 -1
  4. package/README.md +18 -2
  5. package/USAGE.md +55 -11
  6. package/adapters/blazor/FdyTable.razor.cs +66 -7
  7. package/adapters/blazor/TableTypes.cs +6 -0
  8. package/adapters/react/components/FdyTable.tsx +32 -8
  9. package/adapters/vue/components/FdyTable.vue +30 -6
  10. package/dist/freeday.bundle.css +91 -9
  11. package/dist/freeday.css +75 -6
  12. package/dist/freeday.tokens.css +16 -3
  13. package/docs/agent-onboarding.md +153 -0
  14. package/docs/getting-started.md +456 -0
  15. package/docs/integrations.md +321 -0
  16. package/docs/reference-screen.html +461 -0
  17. package/package.json +10 -4
  18. package/src/base.css +15 -0
  19. package/src/components/accordion.css +5 -1
  20. package/src/components/card.css +7 -1
  21. package/src/components/carousel.css +4 -1
  22. package/src/components/list.css +36 -0
  23. package/src/components/table.css +5 -2
  24. package/src/components/tabs.css +2 -1
  25. package/tokens/breakpoints.d.ts +3 -0
  26. package/tokens/breakpoints.mjs +8 -1
  27. package/src/components/.gitkeep +0 -0
  28. package/src/freeday-autocomplete.js +0 -135
  29. package/src/freeday-breakpoint.js +0 -51
  30. package/src/freeday-carousel.js +0 -111
  31. package/src/freeday-cascade.js +0 -256
  32. package/src/freeday-cfl.js +0 -213
  33. package/src/freeday-chart.js +0 -429
  34. package/src/freeday-chip.js +0 -83
  35. package/src/freeday-datepicker.js +0 -321
  36. package/src/freeday-datetime.js +0 -83
  37. package/src/freeday-drawer.js +0 -43
  38. package/src/freeday-form.js +0 -181
  39. package/src/freeday-mask.js +0 -114
  40. package/src/freeday-menu.js +0 -93
  41. package/src/freeday-popover.js +0 -69
  42. package/src/freeday-rating.js +0 -50
  43. package/src/freeday-select.js +0 -218
  44. package/src/freeday-slider.js +0 -34
  45. package/src/freeday-stepper.js +0 -90
  46. package/src/freeday-table.js +0 -475
  47. package/src/freeday-tabs.js +0 -68
  48. package/src/freeday-timepicker.js +0 -180
  49. package/src/freeday-toast.js +0 -105
  50. package/src/freeday-tree.js +0 -94
  51. package/src/freeday-upload.js +0 -206
package/CHANGELOG.md CHANGED
@@ -3,6 +3,233 @@
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.21.0] — 2026-08-12
7
+ Fifth round of real-app consumption feedback, written while that app adopted 1.20.0. Two findings —
8
+ and a **withdrawal**: the reporter retracted 1.20's rejected §A themselves after isolating the real
9
+ mechanism, which turned out to be a genuine kit bug hiding behind it. Both halves of that rejection
10
+ reproduce here, so the rejection stands and the withdrawal is recorded rather than re-litigated.
11
+ ### Fixed
12
+ - **Hidden labels could scroll the whole page.** `.fdy-visually-hidden` is `position:absolute`, and
13
+ `clip` hides *painting*, not *layout*. With no positioned ancestor its containing block is the
14
+ document, and `overflow` clips only what is contained inside the overflow box — so a hidden label in
15
+ a horizontally scrolling table (the kit's own recommended way to name an icon button) parks at its
16
+ static position and drags the document sideways. Measured in Chrome: **1351px** of phantom page
17
+ scroll from 11 spans in one table; `overflow-x:hidden` on the scroller, the shell, `body` and `html`
18
+ each changed it by **0px**; removing the spans took it to 0. Every clipping/scrolling container that
19
+ holds consumer markup now declares `position:relative` — `.fdy-table-scroll`, `.fdy-table-wrap`,
20
+ `.fdy-list`, `.fdy-card`, `.fdy-tabs__list`, `.fdy-carousel__viewport`, `.fdy-accordion` — each
21
+ measured to take its own case to 0 with the scroller still scrolling internally. The rest are
22
+ already inside something the kit positions (`<dialog>`, the sticky sidebar, a fixed popover) and are
23
+ listed with that reason in the new test.
24
+ **`.fdy-accordion` is the one to note:** it was contained only by its panel's reveal *animation*
25
+ (a transform makes a containing block), and that animation sits behind
26
+ `prefers-reduced-motion: no-preference` — so the bug was reachable **only** by readers who asked for
27
+ reduced motion. Measured with the animation off: 2906px → 0.
28
+ *Possible migration:* if you absolutely positioned something inside a card, list or table scroller
29
+ and relied on it escaping, it now anchors to that container. Anchoring is the reason for the change.
30
+ - **`--button` rows and cards ignored `:disabled`.** `.fdy-list__row--button` adopts the UA button box
31
+ but not its disabled state, so a row disabled mid-flight kept its hover tint and pointer cursor — a
32
+ control answering the pointer while refusing input. `:disabled` and `[aria-disabled="true"]` now dim
33
+ it and withdraw hover, for `.fdy-list__row--button`, `.fdy-list__row--interactive`,
34
+ `.fdy-card--button` and `.fdy-card--interactive`. The report suggested `cursor:default`; the kit uses
35
+ `opacity:.5` + `cursor:not-allowed` on every other disabled control, and consistency wins.
36
+ ### Changed
37
+ - **`data-theme` is no longer root-scoped** — the same move density made in 1.20.0, and for the same
38
+ reason. The two *explicit* selectors are now bare `[data-theme="dark"]` / `[data-theme="light"]`, so
39
+ a `<section data-theme="dark">` inverts that region and **every component inside it follows** —
40
+ card surfaces, inputs, and text roles like `.fdy-title-page` that set `color: var(--color-text)`
41
+ explicitly and therefore never saw a consumer's hand-rolled override. A dark brand panel beside a
42
+ light sign-in form is an ordinary layout; it should not cost a re-colouring pass. Setting the
43
+ attribute on `<html>` is unchanged, and a `[data-theme="light"]` island nested inside a dark region
44
+ wins in turn.
45
+ **The system default stays root-scoped, deliberately** — the report asked for "the two generated
46
+ selectors", but there are three. Un-rooting `@media (prefers-color-scheme: dark) { :root:not(...) }`
47
+ would make it match every element that does not itself carry `data-theme="light"`, including the
48
+ *children* of a light island, dragging them back to dark. Measured: with the un-rooted variant that
49
+ island renders light ink on a light surface; root-scoped, it stays correct.
50
+ ### Added — guards
51
+ - **`test/css.test.mjs`** — the containment invariant, CI-gated: a rule that declares `overflow` must
52
+ also be positioned, or be listed with the ancestor that already contains it. Single-line truncation
53
+ (`text-overflow:ellipsis` on a label) is excluded by shape, not by name, so new truncating labels
54
+ don't accumulate in an allowlist. A new clipping container fails the test until someone decides
55
+ which case it is.
56
+ - **`browser/layout.mjs`** — the same bug end-to-end in real Chrome (`npm run test:browser`): ten
57
+ hidden labels in a wide table, asserting the page cannot scroll horizontally *and* that the scroller
58
+ still scrolls. A static test cannot see this failure; only a layout engine can. Both guards
59
+ mutation-checked — reverting any single `position:relative` fails them.
60
+ - **`browser/theme.mjs`** — subtree theming end-to-end: a `.fdy-title-page` and a `.fdy-card` inside
61
+ `<section data-theme="dark">` take the dark tokens, a nested light island goes back, and
62
+ `data-theme` on `<html>` still themes everything. `test/build.test.mjs` guards the selector shape
63
+ (not root-scoped, media block still is, and the block order the cascade depends on); this guards the
64
+ behaviour that shape exists for. Mutation-checked: re-rooting the selectors fails it.
65
+ ### Notes
66
+ - Not adopted from the report, deliberately: `.fdy-datatable`, `.fdy-modal__body`, `.fdy-drawer__body`
67
+ were listed as needing the same fix. Measured: they do not escape — `<dialog>` is `position:fixed`
68
+ and is already their containing block, and the datatable's own scrolling child now carries it. They
69
+ are in the test's allowlist with that reason instead of carrying a declaration that does nothing.
70
+
71
+ ## [1.20.0] — 2026-08-12
72
+ Two bodies of work in one release (1.19.0 was prepared but never committed, tagged or published, so
73
+ it is folded in here rather than left as a phantom version):
74
+ **(a)** make the kit consumable by an **AI coding agent** in a new or migrating project, and clean the
75
+ repo to production level; **(b)** act on the fourth round of real-app consumption feedback — five
76
+ confirmed gaps, one rejected premise, and one documentation bug of our own that chasing it exposed.
77
+ ### Added — from consumption round 4
78
+ - **`.fdy-list` / `.fdy-list__row` — the flat row container** (`src/components/list.css`). One bordered
79
+ surface, `--color-border-muted` hairline dividers, **no shadow**; `--interactive` for hover, and
80
+ `--button` for when the row *is* the control (UA box reset without losing the list surface), plus
81
+ `__main` / `__title` / `__meta` / `__aside` internals. `USAGE.md` §3 has always said list rows should
82
+ be flat, but the only container the kit shipped was `.fdy-card` — which carries `--shadow-lift`, a
83
+ real 34px lift, so a responsive table that becomes a list below `md` had to choose between ten
84
+ floating cards or a hand-built box that needs a colour and escapes the token system.
85
+ - **`FdyTable`: controlled client-side page index.** `pageIndex` + `update:pageIndex` (Vue) /
86
+ `pageIndex` + `onPageIndexChange` (React) / `PageIndex` + `PageIndexChanged` (Blazor). The table
87
+ still filters/sorts/paginates; only *which page* moves to the parent. This is what makes the
88
+ `process` event from 1.18 pay off on a **responsive** screen: the pager renders inside
89
+ `.fdy-datatable`, so a screen that hides the table below `md` loses it — and in client mode the index
90
+ was a private ref with no prop, no event and no `goTo`. The two available options were "lose
91
+ pagination on mobile" or "own the page index in server mode", where `process` hands back exactly the
92
+ array you passed in. One index can now also span several tables, which is what a grouped list needs.
93
+ Reported after a real rebuild where `process` deleted, by measurement, zero lines.
94
+ - **`breakpoints.nav` (721)** in `tokens/breakpoints.mjs` + its type. `.fdy-app` switches the sidebar
95
+ between off-canvas drawer and static column at 721px — a number that was in `app-shell.css` and
96
+ nowhere else, so every consumer of the shell hand-mirrored it. Getting it wrong is not cosmetic:
97
+ aligning to `md` (960) leaves 721–959px with a static sidebar that the script still treats as an
98
+ overlay, so opening the nav makes the page `inert` around a user with no way back out. A new test
99
+ asserts `nav` equals the CSS's `min-width` and that the `max-width` query is `nav - 1`, so the two
100
+ cannot drift.
101
+ - **Blazor `FdyTable` gained `Process`** (+ the `FdyTableProcess<TRow>` record) — 1.18 added the
102
+ `process` event to Vue and React only, which left Blazor unable to drive a card list from the
103
+ processed set at all.
104
+ - **Browser guards for the controlled page index**, Vue and React, in `browser/adapter.mjs`: a table
105
+ whose pager lives *outside* the component, asserting both directions (parent → rows, and internal
106
+ pager → parent event). Mutation-checked: reverting the component to its private index fails them.
107
+ ### Changed — from consumption round 4
108
+ - **`data-density="compact"` is no longer root-scoped.** The generated selector was
109
+ `:root[data-density="compact"]`; it is now a bare `[data-density="compact"]`. These are inheriting
110
+ custom properties, so density can be set on a route wrapper or a single section — which is how it is
111
+ actually decided (per screen), not on `<html>` for the whole app. Setting it on the root still works
112
+ identically. A build test now asserts the selector is not root-scoped.
113
+ ### Fixed — from consumption round 4
114
+ - **`USAGE.md` §3 misdescribed the kit's own elevation scale** — our bug, found while checking the
115
+ report. It prescribed `--shadow-1` for "a card" and `--shadow-4` for "modal / drawer", but `.fdy-card`
116
+ uses `--shadow-lift` (≈6× heavier than `--shadow-1`) and `.fdy-modal` uses `--shadow-lift-hover`;
117
+ `--shadow-1` is what the *data containers* use. §3 now carries the real component→token map, names
118
+ the two shadow families, and points rows at `.fdy-list`. Exactly the drift the repo's own invariant
119
+ warns about: docs restating a scale the components don't follow.
120
+ - **`.fdy-toolbar` vs `.fdy-filterbar` is now documented.** `.fdy-toolbar` is `align-items:center`
121
+ (right for bare controls); a `.fdy-field` with a *visible* label sits half a label-height low in it.
122
+ Labelled fields belong in `.fdy-filterbar` (`align-items:flex-end` — which is why 1.11.2 had to
123
+ arbitrate the composed case). The difference existed but was written down nowhere, so the wrong
124
+ choice was only visible once rendered. Documented in `USAGE.md` §7 and `COMPONENTS.md`; no CSS
125
+ changed, so no existing screen shifts.
126
+ ### Notes — one report item rejected
127
+ - **"`.fdy-page-section` and `.fdy-table-scroll` do not compose" does not reproduce, and the proposed
128
+ `min-width:0` fix is a no-op.** Measured on `docs/reference-screen.html` (the same
129
+ section → datatable → scroller chain) with the table forced to 1400px in a 688px column: page
130
+ overflow **0px**, the datatable held its column, the scroller scrolled internally — and adding
131
+ `min-width:0` changed nothing. Two mechanisms explain it: `.fdy-page-section` is flex **column**, so
132
+ `min-width:auto` (a main-axis rule) cannot cause horizontal growth; and `.fdy-table-scroll` has
133
+ `overflow-x:auto`, which gives it an automatic minimum size of **0**, so no ancestor flex can stretch
134
+ it. The kit also already sets `min-width:0` at the one row-flex boundary it owns
135
+ (`.fdy-app__content`). The 129px overflow the reporter measured is real but originates in their own
136
+ wrapper chain; to locate it, walk the datatable's ancestors at the failing width and find the first
137
+ with `scrollWidth > clientWidth`. Third round in a row where a proposed fix would have changed
138
+ nothing — the premise gets verified before the patch, every time.
139
+ ### Added
140
+ - **`COMPONENTS.md` — the complete public class surface in one flat file.** Every component with its
141
+ block/element/modifier classes, a minimal markup skeleton, its enhancer hook and its a11y contract,
142
+ plus the full enhancer table (markup hook → script → global → events). The gap it closes: 425
143
+ `.fdy-*` classes exist in `src/components/`, but only ~33 appeared as literal strings anywhere in
144
+ the shipped docs — the rest lived in a 2,552-line HTML page and in the CSS source, neither of which
145
+ an agent (or a hurried human) reads.
146
+ - **`docs/agent-onboarding.md`** — the entry point for an agent working in a *consuming* project: a
147
+ paste-ready block for that project's `CLAUDE.md`/`AGENTS.md`, what ships in the package and which
148
+ question each file answers, the order to build a new screen in, a **migration mapping table**
149
+ (Bootstrap / MudBlazor / utility-class conventions → Freeday) with a safe conversion order, and a
150
+ pre-completion verification checklist.
151
+ - **`docs/reference-screen.html`** — one complete business screen assembled the intended way:
152
+ `.fdy-app` → `.fdy-page` → `.fdy-page__header` → `.fdy-stats` → sections holding a chart and a
153
+ full data table, plus a native-`<dialog>` modal, theme/density toggles and the shell's nav-toggle
154
+ wiring. v1.18.0 shipped the composition primitives but nothing demonstrated them end-to-end.
155
+ - **`test/docs.test.mjs` — drift guard for the agent-facing docs.** Every fully-written `.fdy-*`
156
+ class named in `COMPONENTS.md`, `USAGE.md`, `docs/agent-onboarding.md` and
157
+ `docs/reference-screen.html` must exist in the kit (CSS selectors ∪ classes the enhancers
158
+ query/set), and every stylesheet in `src/components/` must be represented in `COMPONENTS.md`. An
159
+ API doc that names a class the CSS never defines is worse than an omission: it invites markup that
160
+ silently does nothing.
161
+ - **`reference/` — the two source assets moved out of the repo root** (`git mv`, so history follows):
162
+ `Foundation Design System.html` → `reference/foundation-design-system.html`, and
163
+ `auth_web_ui_layout_patterns.png` → `reference/layout-patterns.png` (the `auth_` prefix was
164
+ misleading — the sheet is about app layout archetypes, not authentication). Neither was ever in the
165
+ tarball and neither is now; the folder name states that. `reference/README.md` carries their
166
+ provenance plus a **15 archetypes → Freeday primitives** table that names, per archetype, what the
167
+ kit covers and which shapes it has **no** component for (kanban columns, calendar month grid, chat
168
+ bubbles, canvas) — so those get built as layout instead of as invented `fdy-` classes. The drift
169
+ guard checks this file too.
170
+ ### Removed
171
+ - **`src/*.js` no longer ships.** All 24 enhancers in `src/` were **byte-identical** to their `dist/`
172
+ copies, and no `exports` path points into `src/` — so a bundler-based consumer could never import
173
+ them. `files` now lists `src/base.css` + `src/components` (kept: per-component CSS is genuinely
174
+ easier to read than the 117 kB bundle, and `docs/agent-onboarding.md` points agents at it).
175
+ **−25 files, −196 kB unpacked** per install (the compressed tarball barely moves — identical files
176
+ deflate to almost nothing — but the install footprint and "what am I even looking at" do).
177
+ - **4 completed SDD implementation plans + 1 superseded spec deleted** (`docs/superpowers/plans/*`,
178
+ `specs/2026-07-22-…-polish-design.md`, **−1452 lines**). Cited by nobody, served publicly by Pages,
179
+ and describing work that shipped months of releases ago — `CHANGELOG.md` plus git history already
180
+ record it. Only the canonical design spec remains.
181
+ - **`NEXT-UP.md`: 421 → ~125 lines.** Held 15 `Update …` release-log blocks (v1.8.0–v1.18.0), three
182
+ 2026-07-27 post-mortems of resolved items, and a frozen "current condition" snapshot still claiming
183
+ `main` = **v1.7.0** with `npm test` 9/9. A stale snapshot is worse than no snapshot. What's left is
184
+ purely forward-looking: the demand-driven backlog, the deliberate YAGNI list, two durable invariants,
185
+ and the release runbook.
186
+ - **`HANDOFF.md`: 134 → 85 lines.** Its "where we are" section was 90 lines re-narrating every release
187
+ back to v1.3.1 — a third copy of the changelog. Now: current state, then a pointer.
188
+ - `src/components/.gitkeep`, in a directory holding 47 stylesheets.
189
+ ### Fixed
190
+ - **`CLAUDE.md`'s roadmap said "v0.1 (sekarang, token-first)"** at v1.19.0, and listed datepicker,
191
+ data grid, filter bar, pagination, states and wizard as *future* work — all shipped long ago. It is
192
+ the first file every agent session reads, so it was the most expensive stale text in the repo.
193
+ Replaced with the actual status (feature-complete, demand-driven) plus a real structure map that
194
+ distinguishes authored `src/` from generated `dist/`, and names `freeday.bundle.css` as the file to link.
195
+ - **The release runbook listed version-reference locations from memory, and was wrong** — it named
196
+ `examples/*/README.md` (no version in them) and claimed `docs/getting-started.md` has 4 (it has 1).
197
+ Replaced the hand-maintained list with the command that derives it:
198
+ `git grep -n '<old-version>' -- . | grep -v CHANGELOG`.
199
+ - Stale counts trued up: `node --test` 20/20 → **28/28**, "46 komponen" → 47 stylesheets (44 components
200
+ + composition/breakpoints primitives), and the "one-off harness in the session scratchpad" note now
201
+ points at the permanent `browser/` harness.
202
+ - **`CLAUDE.md` claimed the Foundation artifact has base64-embedded fonts that can be re-extracted.**
203
+ It does not: its `@font-face` rules point at dead UUID resources left over from the tool that
204
+ exported it, there is no `data:…;base64` font anywhere in the file, and it renders via the Google
205
+ Fonts CDN it preconnects to. Corrected, so no future session goes looking for fonts that aren't there.
206
+ - **`docs/getting-started.md` §5 pointed consumers at `Foundation Design System.html` for component
207
+ markup** — a file that is not in the npm package, which became a dangling reference the moment this
208
+ release started shipping that doc. Now points at `COMPONENTS.md` and `reference-screen.html`.
209
+ - **`docs/getting-started.md`'s app-shell snippet was structurally wrong** — and it is the first thing
210
+ a consumer copies. It showed `__topbar` as a direct child *before* `__sidebar`, put `__brand` inside
211
+ the topbar, and nested `__content` *inside* `__main`. `.fdy-app` is a flex **row** of
212
+ `[__sidebar | __content]`, `__content` is the column holding `__topbar` + `__main` (it gives the
213
+ sticky topbar a tall containing block), and `__brand` belongs in the sidebar. Copying the old
214
+ snippet rendered the topbar *below* the content, off-screen. Corrected, and the correct nesting is
215
+ now stated in `COMPONENTS.md` and `USAGE.md` too. Caught by driving
216
+ `docs/reference-screen.html` in real Chrome: the nav toggle sat at y≈1021 in a 900px viewport.
217
+ - Same file: "compose the screen inside `__content`" → **`__main`** (which is the padded area).
218
+ ### Changed
219
+ - **`files` now ships the docs an agent needs**: `COMPONENTS.md`, `docs/getting-started.md`,
220
+ `docs/integrations.md`, `docs/agent-onboarding.md`, `docs/reference-screen.html` — listed
221
+ **file-by-file, not as `"docs"`**, so the internal planning docs under `docs/superpowers/` stay out
222
+ of the tarball. (`files` does not honour `.gitignore`; whitelisting a directory ships whatever sits
223
+ inside it — the v1.16.0 `bin/obj` lesson.) Tarball 263.6 kB → 297.9 kB, 177 → 182 files.
224
+ The `examples/` apps are deliberately **not** shipped (127 MB of `node_modules` + 208 MB of .NET
225
+ `bin/obj` live under them); the repo link in `docs/agent-onboarding.md` covers that need.
226
+ ### Notes
227
+ - Documenting the surface surfaced one inconsistency, recorded rather than patched (this release
228
+ touches no CSS): **`.fdy-pagination` has no CSS rule** — the block class on the `<nav>` is a naming
229
+ hook only, its `__list`/`__link`/`__ellipsis` elements carry all the styling, and the data table
230
+ targets `data-fdy-table-pagination`. `COMPONENTS.md` says so, and the drift guard lists it as a
231
+ known structural hook.
232
+
6
233
  ## [1.18.0] — 2026-08-11
7
234
  ### Fixed
8
235
  - **`FdyModal` / `FdyDrawer` (Vue) were non-dismissible when `dismissible` was omitted — an