@cahyo-dimas/freeday 1.54.0 → 2.0.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 (143) hide show
  1. package/CHANGELOG.md +625 -545
  2. package/COMPONENTS.md +141 -138
  3. package/README.id.md +46 -45
  4. package/README.md +46 -43
  5. package/USAGE.md +34 -34
  6. package/adapters/blazor/FdyAppShell.razor +2 -2
  7. package/adapters/blazor/FdyAppShell.razor.cs +6 -6
  8. package/adapters/blazor/FdyCfl.razor.cs +1 -1
  9. package/adapters/blazor/FdyChart.razor +1 -1
  10. package/adapters/blazor/FdyChart.razor.cs +3 -3
  11. package/adapters/blazor/FdyChartSeries.cs +1 -1
  12. package/adapters/blazor/FdyCombo.razor.cs +2 -2
  13. package/adapters/blazor/FdyModal.razor +1 -1
  14. package/adapters/blazor/FdyTable.razor.cs +7 -7
  15. package/adapters/blazor/FdyTableFilter.razor +1 -1
  16. package/adapters/blazor/FdyTableFooter.razor +1 -1
  17. package/adapters/blazor/FdyTableFooter.razor.cs +4 -4
  18. package/adapters/blazor/Freeday.Blazor.csproj +1 -1
  19. package/adapters/blazor/FreedayComponentBase.cs +1 -1
  20. package/adapters/blazor/TableModel.cs +3 -3
  21. package/adapters/blazor/TableTypes.cs +3 -3
  22. package/adapters/blazor/freeday-blazor.js +5 -5
  23. package/adapters/core/app-shell.d.ts +1 -1
  24. package/adapters/core/app-shell.js +6 -6
  25. package/adapters/core/table-model.d.ts +2 -2
  26. package/adapters/core/table-model.js +8 -8
  27. package/adapters/react/components/FdyAppShell.tsx +5 -5
  28. package/adapters/react/components/FdyAutocomplete.tsx +1 -1
  29. package/adapters/react/components/FdyCascade.tsx +1 -1
  30. package/adapters/react/components/FdyCfl.tsx +11 -11
  31. package/adapters/react/components/FdyDateRange.tsx +2 -2
  32. package/adapters/react/components/FdyDatepicker.tsx +5 -5
  33. package/adapters/react/components/FdyDrawer.tsx +1 -1
  34. package/adapters/react/components/FdyModal.tsx +2 -2
  35. package/adapters/react/components/FdyTable.tsx +7 -7
  36. package/adapters/react/components/FdyTableFilter.tsx +1 -1
  37. package/adapters/react/components/FdyTableFooter.tsx +5 -5
  38. package/adapters/react/index.d.ts +1 -1
  39. package/adapters/react/useFreeday.js +3 -3
  40. package/adapters/vue/components/FdyAppShell.vue +5 -5
  41. package/adapters/vue/components/FdyAutocomplete.vue +1 -1
  42. package/adapters/vue/components/FdyCascade.vue +1 -1
  43. package/adapters/vue/components/FdyCfl.vue +8 -8
  44. package/adapters/vue/components/FdyChart.vue +2 -2
  45. package/adapters/vue/components/FdyCombo.vue +1 -1
  46. package/adapters/vue/components/FdyDateRange.vue +2 -2
  47. package/adapters/vue/components/FdyDatepicker.vue +5 -5
  48. package/adapters/vue/components/FdyDrawer.vue +3 -3
  49. package/adapters/vue/components/FdyModal.vue +3 -3
  50. package/adapters/vue/components/FdyTable.vue +7 -7
  51. package/adapters/vue/components/FdyTableFilter.vue +1 -1
  52. package/adapters/vue/components/FdyTableFooter.vue +5 -5
  53. package/adapters/vue/index.d.ts +2 -2
  54. package/adapters/vue/useFreeday.js +3 -3
  55. package/dist/asset.d.ts +3 -3
  56. package/dist/freeday-app-shell.js +9 -9
  57. package/dist/freeday-autocomplete.js +2 -2
  58. package/dist/freeday-breakpoint.js +1 -1
  59. package/dist/freeday-carousel.js +5 -5
  60. package/dist/freeday-cascade.js +7 -7
  61. package/dist/freeday-cfl.js +9 -9
  62. package/dist/freeday-chart.js +11 -11
  63. package/dist/freeday-chip.js +3 -3
  64. package/dist/freeday-datepicker.js +11 -7
  65. package/dist/freeday-datetime.js +5 -5
  66. package/dist/freeday-drawer.js +1 -1
  67. package/dist/freeday-form.js +14 -14
  68. package/dist/freeday-mask.js +6 -6
  69. package/dist/freeday-menu.js +1 -1
  70. package/dist/freeday-number.js +3 -3
  71. package/dist/freeday-popover.js +3 -3
  72. package/dist/freeday-rating.js +2 -2
  73. package/dist/freeday-select.js +5 -5
  74. package/dist/freeday-slider.js +2 -2
  75. package/dist/freeday-stepper.js +7 -7
  76. package/dist/freeday-table.js +15 -15
  77. package/dist/freeday-tabs.js +1 -1
  78. package/dist/freeday-timepicker.js +2 -2
  79. package/dist/freeday-toast.js +8 -8
  80. package/dist/freeday-tree.js +3 -3
  81. package/dist/freeday-upload.js +25 -25
  82. package/dist/freeday.bundle.css +176 -176
  83. package/dist/freeday.css +170 -170
  84. package/dist/freeday.d.ts +2 -2
  85. package/dist/freeday.js +162 -158
  86. package/dist/freeday.tokens.css +5 -5
  87. package/docs/agent-onboarding.md +41 -41
  88. package/docs/getting-started.md +35 -35
  89. package/docs/integrations.md +18 -18
  90. package/docs/reference-screen.html +14 -14
  91. package/package.json +4 -3
  92. package/src/base.css +6 -6
  93. package/src/components/accordion.css +4 -4
  94. package/src/components/alert.css +1 -1
  95. package/src/components/app-shell.css +10 -10
  96. package/src/components/appbar.css +3 -3
  97. package/src/components/autocomplete.css +1 -1
  98. package/src/components/avatar.css +3 -3
  99. package/src/components/badge.css +5 -5
  100. package/src/components/breadcrumb.css +1 -1
  101. package/src/components/breakpoints.css +4 -4
  102. package/src/components/button.css +13 -13
  103. package/src/components/card.css +8 -8
  104. package/src/components/carousel.css +2 -2
  105. package/src/components/cascade.css +2 -2
  106. package/src/components/cfl.css +4 -4
  107. package/src/components/chart.css +3 -3
  108. package/src/components/chip.css +2 -2
  109. package/src/components/combo.css +3 -3
  110. package/src/components/composition.css +7 -7
  111. package/src/components/datepicker.css +6 -6
  112. package/src/components/datetimepicker.css +1 -1
  113. package/src/components/description-list.css +1 -1
  114. package/src/components/divider.css +1 -1
  115. package/src/components/drawer.css +1 -1
  116. package/src/components/file-upload.css +5 -5
  117. package/src/components/filterbar.css +7 -7
  118. package/src/components/form-grid.css +2 -2
  119. package/src/components/input-group.css +6 -6
  120. package/src/components/input.css +6 -6
  121. package/src/components/kbd.css +1 -1
  122. package/src/components/list.css +6 -6
  123. package/src/components/menu.css +3 -3
  124. package/src/components/modal.css +1 -1
  125. package/src/components/pagination.css +1 -1
  126. package/src/components/progress.css +1 -1
  127. package/src/components/rating.css +2 -2
  128. package/src/components/selection.css +4 -4
  129. package/src/components/skeleton.css +1 -1
  130. package/src/components/slider.css +1 -1
  131. package/src/components/spinner.css +1 -1
  132. package/src/components/states.css +1 -1
  133. package/src/components/stepper.css +2 -2
  134. package/src/components/table.css +15 -15
  135. package/src/components/tabs.css +3 -3
  136. package/src/components/timeline.css +1 -1
  137. package/src/components/timepicker.css +1 -1
  138. package/src/components/toast.css +3 -3
  139. package/src/components/tooltip.css +1 -1
  140. package/src/components/tree.css +2 -2
  141. package/tokens/breakpoints.d.ts +2 -2
  142. package/tokens/breakpoints.mjs +3 -3
  143. package/tokens/tokens.json +1 -1
@@ -1,4 +1,4 @@
1
- /* Freeday chart renderer (optional, zero-dependency, no external chart lib).
1
+ /* Freeday, chart renderer (optional, zero-dependency, no external chart lib).
2
2
  * Renders sparkline / bar / line / area / donut into an element from data attributes.
3
3
  * Auto-inits [data-fdy-chart] once; call FreedayChart.update(el) to re-render after the
4
4
  * data attributes change (used by the freeday/vue <FdyChart> wrapper for reactive data).
@@ -6,14 +6,14 @@
6
6
  * Single-series colour (sparkline / simple bar / single line) via data-fdy-color references a
7
7
  * semantic token by name (primary, accent, success, warning, danger, info). Multi-series
8
8
  * defaults draw from the validated categorical --chart-1..8 palette in fixed order (never
9
- * cycled, 8-series cap); pass data-fdy-colors to override a name is a semantic token
9
+ * cycled, 8-series cap); pass data-fdy-colors to override, a name is a semantic token
10
10
  * (var(--color-<name>)) OR a slot "chart-1".."chart-8" (var(--chart-N)) to pin a series to the
11
11
  * validated palette. Both data-fdy-color and data-fdy-colors accept the chart-N form.
12
12
  * Cartesian charts (line/area, multi-series/stacked bar) draw themed axes from --chart-grid /
13
13
  * --chart-tick and format ticks + tooltips via data-fdy-format (number|percent|currency). Their
14
14
  * viewBox is sized to the measured plot (1 user unit = 1 CSS pixel) and repainted from a
15
15
  * ResizeObserver, so axis type stays in real pixels and is set in CSS via --fdy-chart-tick-size.
16
- * Charts are an enhancement put a table/text fallback inside the element and it will be
16
+ * Charts are an enhancement, put a table/text fallback inside the element and it will be
17
17
  * replaced on render; give the element role="img" + aria-label.
18
18
  *
19
19
  * Sparkline: <span data-fdy-chart="sparkline" data-values="4,6,5,8,7,10" data-fdy-color="primary">
@@ -50,7 +50,7 @@
50
50
  return v ? v.split(',').map(function (s) { return s.trim(); }) : [];
51
51
  }
52
52
  // role="img" is Children Presentational per ARIA, so the docs used to say a chart's rendered
53
- // legend, bar values and donut centre are not exposed. No browser actually prunes that subtree
53
+ // legend, bar values and donut centre are not exposed. No browser actually prunes that subtree,
54
54
  // measured in Chrome's AX tree, every one of those nodes is live and unignored; what saves the
55
55
  // advice is only that AT treats a NAMED role="img" as a leaf and does not descend. So the kit
56
56
  // hides them itself, and the author's aria-label really is the whole text alternative.
@@ -225,7 +225,7 @@
225
225
  // Lay the chrome out first so the plot can be measured, then size the viewBox to it in CSS
226
226
  // pixels: one user unit is one pixel, so font-size / r / stroke-width mean what they say at
227
227
  // every container width. (A fixed 320x180 viewBox stretched by CSS multiplied every declared
228
- // size by plotWidth/320 instead a 9px axis label rendered ~39px on a 1728px viewport.)
228
+ // size by plotWidth/320 instead, a 9px axis label rendered ~39px on a 1728px viewport.)
229
229
  var legendMode = el.getAttribute('data-fdy-legend') || 'auto';
230
230
  var showLegend = legendMode !== 'none' && (series.length >= 2 || legendMode === 'always');
231
231
  el.classList.add('fdy-chart-xy');
@@ -246,7 +246,7 @@
246
246
  el.appendChild(plot);
247
247
 
248
248
  // Measured while empty: .fdy-chart-xy__plot carries its own width / aspect-ratio / min-height,
249
- // so the box is already final. A detached or display:none chart measures 0 fall back to the
249
+ // so the box is already final. A detached or display:none chart measures 0, fall back to the
250
250
  // legacy box and let the ResizeObserver repaint it once it is actually laid out.
251
251
  var box = plot.getBoundingClientRect();
252
252
  var W = Math.round(box.width) || 320, H = Math.round(box.height) || 180;
@@ -290,7 +290,7 @@
290
290
 
291
291
  // x category labels with autoskip. Labels are author-supplied, so estimate the widest one instead
292
292
  // of assuming a fixed 40px slot; keep every step-th plus the last, then drop any kept label that
293
- // would collide with the one before it including the forced last one (a fraction-of-a-slot
293
+ // would collide with the one before it, including the forced last one (a fraction-of-a-slot
294
294
  // overlap happens when n-1 lands next to the last kept multiple of step, e.g. n=24 at most widths).
295
295
  var widest = 0;
296
296
  for (var wi = 0; wi < n; wi++) widest = Math.max(widest, String(labels[wi] || ('#' + (wi + 1))).length * charW);
@@ -301,7 +301,7 @@
301
301
  for (var xi = 0; xi < n; xi++) {
302
302
  if (xi % step === 0 || xi === n - 1) kept.push(xi);
303
303
  }
304
- // The last label is worth forcing, but not on top of its neighbour drop the penultimate one.
304
+ // The last label is worth forcing, but not on top of its neighbour, drop the penultimate one.
305
305
  if (kept.length >= 2 && xPos(kept[kept.length - 1]) - xPos(kept[kept.length - 2]) < minGap) {
306
306
  kept.splice(kept.length - 2, 1);
307
307
  }
@@ -434,17 +434,17 @@
434
434
  var li = document.createElement('li');
435
435
  var sw = document.createElement('span'); sw.className = 'fdy-chart__swatch'; sw.style.background = colorAt(i);
436
436
  li.appendChild(sw);
437
- li.appendChild(document.createTextNode((labels[i] || ('#' + (i + 1))) + ' ' + Math.round((v / total) * 100) + '%'));
437
+ li.appendChild(document.createTextNode((labels[i] || ('#' + (i + 1))) + ' · ' + Math.round((v / total) * 100) + '%'));
438
438
  legend.appendChild(li);
439
439
  });
440
440
  el.appendChild(ring);
441
- // Honour data-fdy-legend for the donut too a caller may supply its own richer legend. 'auto'
441
+ // Honour data-fdy-legend for the donut too, a caller may supply its own richer legend. 'auto'
442
442
  // keeps today's behaviour (a donut is unreadable without labels, so it shows); 'none' suppresses it.
443
443
  if ((el.getAttribute('data-fdy-legend') || 'auto') !== 'none') el.appendChild(legend);
444
444
  ensureImg(el);
445
445
  }
446
446
 
447
- // Full (re-)render from current data attributes. Idempotent safe to call repeatedly.
447
+ // Full (re-)render from current data attributes. Idempotent, safe to call repeatedly.
448
448
  function renderChart(el) {
449
449
  var type = el.getAttribute('data-fdy-chart');
450
450
  if (type === 'sparkline') renderSparkline(el);
@@ -1,9 +1,9 @@
1
- /* Freeday chip enhancer (optional, zero-dependency).
1
+ /* Freeday, chip enhancer (optional, zero-dependency).
2
2
  * Two behaviours, both progressive enhancement:
3
3
  *
4
- * 1. Removable chips any .fdy-chip__remove button removes its chip and emits a
4
+ * 1. Removable chips, any .fdy-chip__remove button removes its chip and emits a
5
5
  * bubbling "fdy-chip-remove" (detail {value}).
6
- * 2. Choice / filter groups a [data-fdy-chips] container of interactive chips
6
+ * 2. Choice / filter groups, a [data-fdy-chips] container of interactive chips
7
7
  * (.fdy-chip--choice / .fdy-chip--filter, each a <button>) toggles aria-pressed
8
8
  * on click. Add data-single for one-at-a-time (radio-like) selection; filter
9
9
  * chips get a leading check when pressed. Emits "fdy-chip-change" on the group
@@ -1,6 +1,6 @@
1
- /* Freeday date picker enhancer (optional, zero-dependency).
1
+ /* Freeday, date picker enhancer (optional, zero-dependency).
2
2
  * Builds an input-styled trigger + calendar popover from an empty wrapper.
3
- * Locale comes from <html lang> (via Intl) month/weekday/value formatting is not hardcoded.
3
+ * Locale comes from <html lang> (via Intl), month/weekday/value formatting is not hardcoded.
4
4
  *
5
5
  * Markup contract:
6
6
  * - Single: <div data-fdy-datepicker data-value="2026-07-21" data-label="Tanggal unggah"
@@ -19,7 +19,11 @@
19
19
  (function () {
20
20
  'use strict';
21
21
 
22
- var LOCALE = document.documentElement.getAttribute('lang') || 'id';
22
+ /* The page's own `lang` wins, which is the better escape hatch than any attribute the kit
23
+ could invent: an Indonesian app writes <html lang="id"> and gets Indonesian month and
24
+ weekday names back automatically. The FALLBACK follows the kit's default language, or a
25
+ page without `lang` would read English labels around Indonesian month names. */
26
+ var LOCALE = document.documentElement.getAttribute('lang') || 'en';
23
27
  var uidSeq = 0;
24
28
  function uid(p) { uidSeq += 1; return p + '-' + uidSeq; }
25
29
  function pad(n) { return n < 10 ? '0' + n : '' + n; }
@@ -66,10 +70,10 @@
66
70
  var view = startOfDay(selected || new Date());
67
71
  view = new Date(view.getFullYear(), view.getMonth(), 1);
68
72
  var focusDate = null;
69
- /* 'days' | 'months' the calendar drills one level up rather than growing furniture beside the
73
+ /* 'days' | 'months', the calendar drills one level up rather than growing furniture beside the
70
74
  title. Before this, the only pointer route to another month was one click per month: from
71
75
  August 2026 to March 2022 is fifty-three of them. Shift+PageUp already jumped a year, but a
72
- shortcut nobody can see is not an affordance the repo's own test helper clicked "previous
76
+ shortcut nobody can see is not an affordance, the repo's own test helper clicked "previous
73
77
  month" twenty-four times to reach a date two years back. */
74
78
  var mode = 'days';
75
79
  var focusMonth = null;
@@ -268,7 +272,7 @@
268
272
  var YEARS_PER_PAGE = 12;
269
273
  function yearPageStart(y) { return Math.floor(y / YEARS_PER_PAGE) * YEARS_PER_PAGE; }
270
274
 
271
- /* A year is only unreachable when EVERY month in it falls outside min/max the same rule
275
+ /* A year is only unreachable when EVERY month in it falls outside min/max, the same rule
272
276
  monthDisabled applies one level down, for the same reason: a bound that sits inside the year
273
277
  disables neither end. */
274
278
  function yearDisabled(y) {
@@ -513,7 +517,7 @@
513
517
  var f = fromApi.getValue();
514
518
  var t = toApi.getValue();
515
519
  toApi.setMin(f || null); // end can't precede start (one-directional, per Foundation)
516
- fromApi.setRange(f, t); // start stays free picking a later start clears the end below
520
+ fromApi.setRange(f, t); // start stays free, picking a later start clears the end below
517
521
  toApi.setRange(f, t);
518
522
  }
519
523
  fromEl.addEventListener('fdy-datepicker-change', function () {
@@ -1,6 +1,6 @@
1
- /* Freeday datetime picker composer (optional, zero-dependency).
1
+ /* Freeday, datetime picker composer (optional, zero-dependency).
2
2
  * Combines a child date picker and time picker into one value. It does not build
3
- * anything itself freeday-datepicker.js and freeday-timepicker.js enhance the
3
+ * anything itself, freeday-datepicker.js and freeday-timepicker.js enhance the
4
4
  * children; this only listens for their change events and emits a single combined
5
5
  * "fdy-datetime-change" (detail {date, time, value}). value is "YYYY-MM-DDTHH:MM"
6
6
  * when both parts are set, else "". Icon variants are controlled per child picker
@@ -10,7 +10,7 @@
10
10
  * <div data-fdy-datepicker data-value="2026-07-21"></div>
11
11
  * <div data-fdy-timepicker data-value="14:30"></div></div>
12
12
  * State: add data-fdy-disabled or data-fdy-invalid on the wrapper to reflect it onto both
13
- * child triggers as one control (read-only is adapter-only a vanilla datetime is interactive).
13
+ * child triggers as one control (read-only is adapter-only, a vanilla datetime is interactive).
14
14
  */
15
15
  (function () {
16
16
  'use strict';
@@ -25,7 +25,7 @@
25
25
  if (!dp || !tp) return;
26
26
 
27
27
  // Reflect one wrapper-level state onto BOTH child triggers so a datetime reads as a single
28
- // disabled/invalid control. Deferred with setTimeout(0) NOT a microtask: the timepicker
28
+ // disabled/invalid control. Deferred with setTimeout(0). NOT a microtask: the timepicker
29
29
  // enhancer registers its DOMContentLoaded init AFTER this composer, and microtasks drain
30
30
  // *between* listeners (so a microtask would run before the timepicker trigger exists). A
31
31
  // macrotask waits until the whole init pass is done and both triggers are built. (readonly is
@@ -56,7 +56,7 @@
56
56
  }));
57
57
  }
58
58
 
59
- // Listen for the children's bubbling change events (order-independent no need
59
+ // Listen for the children's bubbling change events (order-independent, no need
60
60
  // for the child enhancers to have run before this composer).
61
61
  wrap.addEventListener('fdy-datepicker-change', function (e) { date = e.detail.value; emit(); });
62
62
  wrap.addEventListener('fdy-time-select', function (e) { time = e.detail.value; emit(); });
@@ -1,4 +1,4 @@
1
- /* Freeday drawer enhancer (optional, zero-dependency).
1
+ /* Freeday, drawer enhancer (optional, zero-dependency).
2
2
  * A trigger [data-fdy-drawer="drawerId"] opens the <dialog class="fdy-drawer" id="drawerId">
3
3
  * as a modal side panel (native showModal gives focus-trap, Esc, and return-focus). Clicking
4
4
  * the backdrop or any [data-close] inside closes it.
@@ -1,4 +1,4 @@
1
- /* Freeday form validation enhancer (optional, zero-dependency).
1
+ /* Freeday, form validation enhancer (optional, zero-dependency).
2
2
  * Wires the native Constraint Validation API to accessible inline errors on any
3
3
  * [data-fdy-validate] <form>. Native-first: constraints come from the standard
4
4
  * markup attributes (required, type, pattern, min/max, minlength/maxlength, step);
@@ -38,24 +38,24 @@
38
38
  badInput: 'type',
39
39
  customError: 'mismatch'
40
40
  };
41
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
42
- * path and overridable at three levels, narrowest first: `data-fdy-msg-<alias>` on the field,
41
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
42
+ * path, and overridable at three levels, narrowest first: `data-fdy-msg-<alias>` on the field,
43
43
  * `data-fdy-msg` on the field, then `data-fdy-text-<alias>` on the FORM. The form level is what
44
44
  * a host in another language needs: it sets nine messages once instead of on every input.
45
45
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
46
46
  var TEXT = {
47
- required: 'Wajib diisi.',
48
- type: 'Format tidak valid.',
49
- pattern: 'Format tidak sesuai.',
50
- minlength: 'Terlalu pendek.',
51
- maxlength: 'Terlalu panjang.',
52
- min: 'Nilai terlalu kecil.',
53
- max: 'Nilai terlalu besar.',
54
- step: 'Nilai tidak sesuai kelipatan.',
55
- mismatch: 'Nilai tidak cocok.',
56
- invalid: 'Tidak valid.'
47
+ required: 'Required.',
48
+ type: 'Invalid format.',
49
+ pattern: 'Doesn’t match the required format.',
50
+ minlength: 'Too short.',
51
+ maxlength: 'Too long.',
52
+ min: 'Too small.',
53
+ max: 'Too large.',
54
+ step: 'Not a valid step.',
55
+ mismatch: 'Values don’t match.',
56
+ invalid: 'Invalid.'
57
57
  };
58
- /* Kebab-cased for the lookup see the note in the other enhancers: HTML lowercases attribute
58
+ /* Kebab-cased for the lookup, see the note in the other enhancers: HTML lowercases attribute
59
59
  names, so `data-fdy-text-filter-text` and `data-fdy-text-filtertext` are different attributes
60
60
  and only one of them is what an author would write. */
61
61
  function textOf(root, key) {
@@ -1,4 +1,4 @@
1
- /* Freeday input mask + password reveal enhancer (optional, zero-dependency).
1
+ /* Freeday, input mask + password reveal enhancer (optional, zero-dependency).
2
2
  *
3
3
  * [data-fdy-mask]="pattern" formats a text input as you type. Placeholders:
4
4
  * # a digit (0-9) A a letter (a-z/A-Z) * a letter or digit
@@ -51,16 +51,16 @@
51
51
  }
52
52
 
53
53
 
54
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
55
- * path and every one overridable per element, so a host that speaks another language (the
54
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
55
+ * path, and every one overridable per element, so a host that speaks another language (the
56
56
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
57
57
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
58
58
  var TEXT = {
59
- show: 'Tampilkan kata sandi',
60
- hide: 'Sembunyikan kata sandi'
59
+ show: 'Show password',
60
+ hide: 'Hide password'
61
61
  };
62
62
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
63
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
63
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
64
64
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
65
65
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
66
66
  still resolves, for markup written against 1.39.0. */
@@ -1,4 +1,4 @@
1
- /* Freeday menu enhancer (optional, zero-dependency).
1
+ /* Freeday, menu enhancer (optional, zero-dependency).
2
2
  * Menu-button pattern (WAI-ARIA APG): a trigger with aria-haspopup="menu" toggles a
3
3
  * role="menu" popup of role="menuitem" buttons. Also powers the split button
4
4
  * (main action + attached caret toggle). Auto-inits [data-fdy-menu].
@@ -1,7 +1,7 @@
1
- /* Freeday number field enhancer (optional, zero-dependency).
1
+ /* Freeday, number field enhancer (optional, zero-dependency).
2
2
  * Gives a native <input type="number"> its increment/decrement affordance back, on the kit's terms:
3
3
  * .fdy-input hides the user agent's own spin buttons (unthemeable OS widgets), so this puts two real
4
- * buttons in an .fdy-input-group instead. No new block the group already owns the shared border,
4
+ * buttons in an .fdy-input-group instead. No new block, the group already owns the shared border,
5
5
  * :focus-within ring and error promotion.
6
6
  *
7
7
  * Markup contract:
@@ -67,7 +67,7 @@
67
67
  if (frozen()) return;
68
68
  if (Number(btn.getAttribute('data-fdy-number-step')) < 0) input.stepDown();
69
69
  else input.stepUp();
70
- /* The value changed without the user typing, so say so the way the platform does frameworks
70
+ /* The value changed without the user typing, so say so the way the platform does, frameworks
71
71
  listen to these, not to a kit-specific event. */
72
72
  input.dispatchEvent(new Event('input', { bubbles: true }));
73
73
  input.dispatchEvent(new Event('change', { bubbles: true }));
@@ -1,7 +1,7 @@
1
- /* Freeday popover positioning helper (optional, zero-dependency).
1
+ /* Freeday, popover positioning helper (optional, zero-dependency).
2
2
  * Lifts a dropdown panel into the top layer via the native Popover API so it escapes ANY
3
3
  * ancestor overflow clip (a .fdy-card with overflow:hidden, an app-shell main with
4
- * overflow:auto, …), then positions it `fixed` against its trigger flipping above when
4
+ * overflow:auto, …), then positions it `fixed` against its trigger, flipping above when
5
5
  * there is no room below, and matching the trigger width. The panel stays a DOM child of its
6
6
  * component, so focus, outside-click (.closest), and ARIA relationships keep working unchanged.
7
7
  *
@@ -21,7 +21,7 @@
21
21
  && typeof HTMLElement.prototype.showPopover === 'function';
22
22
 
23
23
  // Position `panel` (already shown, so it has a measurable box) against `trigger`'s rect.
24
- // matchWidth (default true) floors the panel to the trigger width right for input-shaped
24
+ // matchWidth (default true) floors the panel to the trigger width, right for input-shaped
25
25
  // dropdowns (combo/cascade/date/time), skipped for menus that keep their own min-width.
26
26
  function place(panel, trigger, matchWidth) {
27
27
  var r = trigger.getBoundingClientRect();
@@ -1,7 +1,7 @@
1
- /* Freeday rating enhancer (optional, zero-dependency).
1
+ /* Freeday, rating enhancer (optional, zero-dependency).
2
2
  * Fills stars up to the checked radio (and previews on hover) for an interactive
3
3
  * [data-fdy-rating] radio group; for [data-fdy-readonly] it fills from data-value.
4
- * The radios are native arrow-key selection and form association come for free.
4
+ * The radios are native, arrow-key selection and form association come for free.
5
5
  */
6
6
  (function () {
7
7
  'use strict';
@@ -1,8 +1,8 @@
1
- /* Freeday combobox enhancer (optional, zero-dependency).
1
+ /* Freeday, combobox enhancer (optional, zero-dependency).
2
2
  * Implements the WAI-ARIA APG "select-only combobox" pattern for every
3
3
  * [data-fdy-combo] on the page. Progressive enhancement: the markup is the
4
4
  * component, this script wires behavior. In a Vue/React/Blazor app you would
5
- * bind your own state instead this is the framework-agnostic reference.
5
+ * bind your own state instead, this is the framework-agnostic reference.
6
6
  *
7
7
  * Expected markup:
8
8
  * <div class="fdy-combo" data-fdy-combo data-value="x">
@@ -25,7 +25,7 @@
25
25
  var seq = 0;
26
26
  var openClose = null; // close() of the currently-open combo, or null
27
27
 
28
- /* The tick lives in CSS now, so the option's text IS its label no sibling walk to skip a glyph. */
28
+ /* The tick lives in CSS now, so the option's text IS its label, no sibling walk to skip a glyph. */
29
29
  function optionLabel(opt) {
30
30
  return (opt.textContent || '').trim();
31
31
  }
@@ -91,7 +91,7 @@
91
91
  if (openClose === close) openClose = null;
92
92
  }
93
93
  // Mark an option selected + reflect it in the button. `silent` skips the change
94
- // event, close, and focus used by the programmatic setValue() below so a host
94
+ // event, close, and focus, used by the programmatic setValue() below so a host
95
95
  // (e.g. a Blazor/framework wrapper) can push a value in without echoing an event
96
96
  // back to itself or stealing focus. User-driven picks go through choose() (loud).
97
97
  function select(opt, silent) {
@@ -126,7 +126,7 @@
126
126
  isOpen() ? close() : open();
127
127
  });
128
128
  // Pressing an option must not blur the button: a blur fires the focusout
129
- // handler below, which closes the listbox before the option's click lands
129
+ // handler below, which closes the listbox before the option's click lands,
130
130
  // so the pick is lost (real mouse only; synthetic .click() never blurs).
131
131
  // preventDefault on mousedown keeps focus on the button without blocking click.
132
132
  listbox.addEventListener('mousedown', function (e) { e.preventDefault(); });
@@ -1,7 +1,7 @@
1
- /* Freeday slider value binding (optional, zero-dependency).
1
+ /* Freeday, slider value binding (optional, zero-dependency).
2
2
  * Mirrors a [data-fdy-slider] range input's value into <output for="inputId">, with an
3
3
  * optional prefix/suffix on the output (data-fdy-prefix / data-fdy-suffix). The range itself
4
- * is a native input keyboard and ARIA are built in; this only updates the visible readout.
4
+ * is a native input, keyboard and ARIA are built in; this only updates the visible readout.
5
5
  */
6
6
  (function () {
7
7
  'use strict';
@@ -1,6 +1,6 @@
1
- /* Freeday stepper/wizard enhancer (optional, zero-dependency).
1
+ /* Freeday, stepper/wizard enhancer (optional, zero-dependency).
2
2
  * Drives a step header + panels: prev/next navigation, completed/active state, and
3
- * clicking a reached step to revisit it (linear can't skip ahead). Auto-inits
3
+ * clicking a reached step to revisit it (linear, can't skip ahead). Auto-inits
4
4
  * [data-fdy-stepper].
5
5
  *
6
6
  * Markup: <div data-fdy-stepper>
@@ -19,16 +19,16 @@
19
19
  var CHECK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg>';
20
20
 
21
21
 
22
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
23
- * path and every one overridable per element, so a host that speaks another language (the
22
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
23
+ * path, and every one overridable per element, so a host that speaks another language (the
24
24
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
25
25
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
26
26
  var TEXT = {
27
- done: 'Selesai',
28
- next: 'Lanjut'
27
+ done: 'Done',
28
+ next: 'Next'
29
29
  };
30
30
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
31
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
31
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
32
32
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
33
33
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
34
34
  still resolves, for markup written against 1.39.0. */
@@ -1,4 +1,4 @@
1
- /* Freeday data-table enhancer (optional, zero-dependency).
1
+ /* Freeday, data-table enhancer (optional, zero-dependency).
2
2
  * Adds client-side search, column sort, pagination and row selection to any
3
3
  * [data-fdy-table]. Progressive enhancement over a plain semantic <table>;
4
4
  * in a framework app, do this server- or store-side instead.
@@ -34,26 +34,26 @@
34
34
  }
35
35
 
36
36
 
37
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
38
- * path and every one overridable per element, so a host that speaks another language (the
37
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
38
+ * path, and every one overridable per element, so a host that speaks another language (the
39
39
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
40
40
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
41
41
  var TEXT = {
42
- prev: 'Sebelumnya',
43
- next: 'Berikutnya',
44
- selected: '{n} dipilih',
45
- filter: 'Filter kolom',
46
- filterText: 'Berisi teks',
47
- filterTextPlaceholder: 'Berisi…',
48
- filterEnum: 'Tampilkan nilai',
49
- filterRange: 'Rentang nilai',
42
+ prev: 'Previous',
43
+ next: 'Next',
44
+ selected: '{n} selected',
45
+ filter: 'Filter column',
46
+ filterText: 'Contains text',
47
+ filterTextPlaceholder: 'Contains…',
48
+ filterEnum: 'Show values',
49
+ filterRange: 'Value range',
50
50
  reset: 'Reset',
51
- close: 'Tutup',
52
- rows: '{n} baris',
53
- info: 'Menampilkan {from}–{to} dari {total}'
51
+ close: 'Close',
52
+ rows: '{n} rows',
53
+ info: 'Showing {from}–{to} of {total}'
54
54
  };
55
55
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
56
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
56
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
57
57
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
58
58
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
59
59
  still resolves, for markup written against 1.39.0. */
@@ -1,4 +1,4 @@
1
- /* Freeday tabs enhancer (optional, zero-dependency, WAI-ARIA APG tabs).
1
+ /* Freeday, tabs enhancer (optional, zero-dependency, WAI-ARIA APG tabs).
2
2
  * Auto-inits every [data-fdy-tabs]. Roving tabindex + arrow/Home/End nav.
3
3
  *
4
4
  * Markup: a [data-fdy-tabs] with a [role="tablist"] of
@@ -1,4 +1,4 @@
1
- /* Freeday time picker enhancer (optional, zero-dependency).
1
+ /* Freeday, time picker enhancer (optional, zero-dependency).
2
2
  * Builds an input-styled trigger + scrollable time-list popover (WAI-ARIA listbox)
3
3
  * from an empty [data-fdy-timepicker] wrapper. 24h HH:MM. Options run from
4
4
  * data-min (default 00:00) to data-max (default 23:59) every data-step minutes
@@ -28,7 +28,7 @@
28
28
  wrap.dataset.fdyTpReady = '1';
29
29
  wrap.classList.add('fdy-timepicker');
30
30
 
31
- var label = wrap.getAttribute('data-label') || 'Pilih waktu';
31
+ var label = wrap.getAttribute('data-label') || 'Choose a time';
32
32
  var placeholder = wrap.getAttribute('data-placeholder') || '--:--';
33
33
  var step = Math.max(1, parseInt(wrap.getAttribute('data-step') || '30', 10));
34
34
  var minM = valid(wrap.getAttribute('data-min')) ? toMin(wrap.getAttribute('data-min')) : 0;
@@ -1,9 +1,9 @@
1
- /* Freeday toast API (optional, zero-dependency).
1
+ /* Freeday, toast API (optional, zero-dependency).
2
2
  * Freeday.toast({ variant, title, message, timeout, key }) shows a transient
3
3
  * notification in a live region (created on first use). Returns the element.
4
4
  * variant: 'success' | 'warning' | 'danger' | 'info' (default: neutral)
5
5
  * timeout: ms before auto-dismiss (default 4000; 0 = sticky)
6
- * key: optional stable id a new toast with the same key REPLACES the
6
+ * key: optional stable id, a new toast with the same key REPLACES the
7
7
  * existing one in place instead of stacking a duplicate (e.g. a burst
8
8
  * of identical failures shows one toast, refreshed).
9
9
  * Freeday.dismiss(nodeOrKey) closes a toast early (pass the returned element or its key).
@@ -39,14 +39,14 @@
39
39
 
40
40
  /* Put the region in the TOP LAYER, above any open <dialog>.
41
41
  *
42
- * A modal dialog lives in the top layer, where z-index does not reach so a toast raised by an
42
+ * A modal dialog lives in the top layer, where z-index does not reach, so a toast raised by an
43
43
  * action taken inside a modal was painted behind that modal's backdrop, which is where an error
44
44
  * message is least useful. showPopover() joins the same layer, and membership there is ordered by
45
45
  * when you joined: hide-then-show re-joins at the top, so a toast shown while a dialog is open
46
46
  * lands above it rather than under the dialog that was opened after the last toast.
47
47
  *
48
48
  * Guarded twice on purpose. `showPopover` is absent before Chrome 114 / Safari 17 / Firefox 125,
49
- * and the call throws if the element is disconnected or already open in every one of those
49
+ * and the call throws if the element is disconnected or already open, in every one of those
50
50
  * cases the region stays an ordinary fixed block at z-index 200, which is what it has always
51
51
  * been. A notification must never be the thing that throws.
52
52
  */
@@ -77,15 +77,15 @@
77
77
  }
78
78
 
79
79
 
80
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
81
- * path and every one overridable per element, so a host that speaks another language (the
80
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
81
+ * path, and every one overridable per element, so a host that speaks another language (the
82
82
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
83
83
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
84
84
  var TEXT = {
85
- close: 'Tutup'
85
+ close: 'Close'
86
86
  };
87
87
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
88
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
88
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
89
89
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
90
90
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
91
91
  still resolves, for markup written against 1.39.0. */
@@ -1,7 +1,7 @@
1
- /* Freeday tree checkbox cascade (optional, zero-dependency).
1
+ /* Freeday, tree checkbox cascade (optional, zero-dependency).
2
2
  * Turns a [data-fdy-tree] checkbox tree into a selectable one: checking a branch checks
3
3
  * every descendant; a partially-selected branch shows the native :indeterminate state.
4
- * Rows are native <input class="fdy-checkbox">, labelled via aria-label Space toggles.
4
+ * Rows are native <input class="fdy-checkbox">, labelled via aria-label. Space toggles.
5
5
  * Selection never toggles the <details> (the checkbox stops click propagation).
6
6
  *
7
7
  * Markup contract:
@@ -25,7 +25,7 @@
25
25
  return Array.prototype.filter.call(ul.children, function (n) { return n.tagName === 'LI'; });
26
26
  }
27
27
 
28
- // The checkbox belonging to a row's own <li> branch summary or leaf, never a child's.
28
+ // The checkbox belonging to a row's own <li>, branch summary or leaf, never a child's.
29
29
  function ownBox(li) {
30
30
  return li.querySelector(':scope > details > summary input[type="checkbox"]')
31
31
  || li.querySelector(':scope > input[type="checkbox"]');