@cahyo-dimas/freeday 1.41.0 → 1.46.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.
package/dist/freeday.js CHANGED
@@ -219,8 +219,18 @@
219
219
  position: '{n} dari {total}',
220
220
  slide: 'Slide {n}'
221
221
  };
222
+ /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
223
+ as `data-fdy-text-filtertext` — while the kebab form anybody would reach for,
224
+ `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
225
+ override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
226
+ still resolves, for markup written against 1.39.0. */
227
+ function textAttr(root, key) {
228
+ if (!root || !root.getAttribute) return null;
229
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
230
+ return kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
231
+ }
222
232
  function textOf(root, key, vars) {
223
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
233
+ var custom = textAttr(root, key);
224
234
  var s = custom != null && custom !== '' ? custom : TEXT[key];
225
235
  if (vars) for (var k in vars) if (Object.prototype.hasOwnProperty.call(vars, k)) s = s.split('{' + k + '}').join(vars[k]);
226
236
  return s;
@@ -386,8 +396,18 @@
386
396
  back: 'Kembali satu tingkat',
387
397
  submenu: '{label}, submenu'
388
398
  };
399
+ /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
400
+ as `data-fdy-text-filtertext` — while the kebab form anybody would reach for,
401
+ `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
402
+ override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
403
+ still resolves, for markup written against 1.39.0. */
404
+ function textAttr(root, key) {
405
+ if (!root || !root.getAttribute) return null;
406
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
407
+ return kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
408
+ }
389
409
  function textOf(root, key, vars) {
390
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
410
+ var custom = textAttr(root, key);
391
411
  var s = custom != null && custom !== '' ? custom : TEXT[key];
392
412
  if (vars) for (var k in vars) if (Object.prototype.hasOwnProperty.call(vars, k)) s = s.split('{' + k + '}').join(vars[k]);
393
413
  return s;
@@ -641,8 +661,18 @@
641
661
  var TEXT = {
642
662
  selected: '{n} dipilih'
643
663
  };
664
+ /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
665
+ as `data-fdy-text-filtertext` — while the kebab form anybody would reach for,
666
+ `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
667
+ override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
668
+ still resolves, for markup written against 1.39.0. */
669
+ function textAttr(root, key) {
670
+ if (!root || !root.getAttribute) return null;
671
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
672
+ return kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
673
+ }
644
674
  function textOf(root, key, vars) {
645
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
675
+ var custom = textAttr(root, key);
646
676
  var s = custom != null && custom !== '' ? custom : TEXT[key];
647
677
  if (vars) for (var k in vars) if (Object.prototype.hasOwnProperty.call(vars, k)) s = s.split('{' + k + '}').join(vars[k]);
648
678
  return s;
@@ -2094,8 +2124,13 @@
2094
2124
  mismatch: 'Nilai tidak cocok.',
2095
2125
  invalid: 'Tidak valid.'
2096
2126
  };
2127
+ /* Kebab-cased for the lookup — see the note in the other enhancers: HTML lowercases attribute
2128
+ names, so `data-fdy-text-filter-text` and `data-fdy-text-filtertext` are different attributes
2129
+ and only one of them is what an author would write. */
2097
2130
  function textOf(root, key) {
2098
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
2131
+ if (!root || !root.getAttribute) return TEXT[key];
2132
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
2133
+ var custom = kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
2099
2134
  return custom != null && custom !== '' ? custom : TEXT[key];
2100
2135
  }
2101
2136
  var VALIDITY_KEYS = ['valueMissing', 'typeMismatch', 'patternMismatch', 'tooShort', 'tooLong', 'rangeUnderflow', 'rangeOverflow', 'stepMismatch', 'badInput'];
@@ -2294,8 +2329,18 @@
2294
2329
  show: 'Tampilkan kata sandi',
2295
2330
  hide: 'Sembunyikan kata sandi'
2296
2331
  };
2332
+ /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
2333
+ as `data-fdy-text-filtertext` — while the kebab form anybody would reach for,
2334
+ `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
2335
+ override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
2336
+ still resolves, for markup written against 1.39.0. */
2337
+ function textAttr(root, key) {
2338
+ if (!root || !root.getAttribute) return null;
2339
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
2340
+ return kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
2341
+ }
2297
2342
  function textOf(root, key, vars) {
2298
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
2343
+ var custom = textAttr(root, key);
2299
2344
  var s = custom != null && custom !== '' ? custom : TEXT[key];
2300
2345
  if (vars) for (var k in vars) if (Object.prototype.hasOwnProperty.call(vars, k)) s = s.split('{' + k + '}').join(vars[k]);
2301
2346
  return s;
@@ -2975,8 +3020,18 @@
2975
3020
  done: 'Selesai',
2976
3021
  next: 'Lanjut'
2977
3022
  };
3023
+ /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
3024
+ as `data-fdy-text-filtertext` — while the kebab form anybody would reach for,
3025
+ `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
3026
+ override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
3027
+ still resolves, for markup written against 1.39.0. */
3028
+ function textAttr(root, key) {
3029
+ if (!root || !root.getAttribute) return null;
3030
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
3031
+ return kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
3032
+ }
2978
3033
  function textOf(root, key, vars) {
2979
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
3034
+ var custom = textAttr(root, key);
2980
3035
  var s = custom != null && custom !== '' ? custom : TEXT[key];
2981
3036
  if (vars) for (var k in vars) if (Object.prototype.hasOwnProperty.call(vars, k)) s = s.split('{' + k + '}').join(vars[k]);
2982
3037
  return s;
@@ -3110,8 +3165,18 @@
3110
3165
  rows: '{n} baris',
3111
3166
  info: 'Menampilkan {from}–{to} dari {total}'
3112
3167
  };
3168
+ /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
3169
+ as `data-fdy-text-filtertext` — while the kebab form anybody would reach for,
3170
+ `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
3171
+ override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
3172
+ still resolves, for markup written against 1.39.0. */
3173
+ function textAttr(root, key) {
3174
+ if (!root || !root.getAttribute) return null;
3175
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
3176
+ return kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
3177
+ }
3113
3178
  function textOf(root, key, vars) {
3114
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
3179
+ var custom = textAttr(root, key);
3115
3180
  var s = custom != null && custom !== '' ? custom : TEXT[key];
3116
3181
  if (vars) for (var k in vars) if (Object.prototype.hasOwnProperty.call(vars, k)) s = s.split('{' + k + '}').join(vars[k]);
3117
3182
  return s;
@@ -3892,8 +3957,18 @@
3892
3957
  var TEXT = {
3893
3958
  close: 'Tutup'
3894
3959
  };
3960
+ /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
3961
+ as `data-fdy-text-filtertext` — while the kebab form anybody would reach for,
3962
+ `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
3963
+ override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
3964
+ still resolves, for markup written against 1.39.0. */
3965
+ function textAttr(root, key) {
3966
+ if (!root || !root.getAttribute) return null;
3967
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
3968
+ return kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
3969
+ }
3895
3970
  function textOf(root, key, vars) {
3896
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
3971
+ var custom = textAttr(root, key);
3897
3972
  var s = custom != null && custom !== '' ? custom : TEXT[key];
3898
3973
  if (vars) for (var k in vars) if (Object.prototype.hasOwnProperty.call(vars, k)) s = s.split('{' + k + '}').join(vars[k]);
3899
3974
  return s;
@@ -4119,8 +4194,18 @@
4119
4194
  badType: 'Tipe berkas tidak didukung.',
4120
4195
  tooBig: 'Ukuran melebihi batas ({max}).'
4121
4196
  };
4197
+ /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
4198
+ as `data-fdy-text-filtertext` — while the kebab form anybody would reach for,
4199
+ `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
4200
+ override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
4201
+ still resolves, for markup written against 1.39.0. */
4202
+ function textAttr(root, key) {
4203
+ if (!root || !root.getAttribute) return null;
4204
+ var kebab = root.getAttribute('data-fdy-text-' + key.replace(/[A-Z]/g, function (c) { return '-' + c.toLowerCase(); }));
4205
+ return kebab != null && kebab !== '' ? kebab : root.getAttribute('data-fdy-text-' + key);
4206
+ }
4122
4207
  function textOf(root, key, vars) {
4123
- var custom = root && root.getAttribute ? root.getAttribute('data-fdy-text-' + key) : null;
4208
+ var custom = textAttr(root, key);
4124
4209
  var s = custom != null && custom !== '' ? custom : TEXT[key];
4125
4210
  if (vars) for (var k in vars) if (Object.prototype.hasOwnProperty.call(vars, k)) s = s.split('{' + k + '}').join(vars[k]);
4126
4211
  return s;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cahyo-dimas/freeday",
3
- "version": "1.41.0",
3
+ "version": "1.46.0",
4
4
  "description": "Freeday — token-driven, framework-agnostic UI KIT (design source-of-truth).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -92,7 +92,7 @@
92
92
  "scripts": {
93
93
  "build": "node tokens/build.mjs",
94
94
  "test": "node --test",
95
- "test:browser": "node --test browser/vanilla.mjs browser/adapter.mjs browser/layout.mjs browser/theme.mjs browser/state.mjs browser/root-init.mjs browser/upload-states.mjs browser/number.mjs browser/card-stretch.mjs browser/text-override.mjs browser/control-heights.mjs",
95
+ "test:browser": "node --test browser/vanilla.mjs browser/adapter.mjs browser/layout.mjs browser/theme.mjs browser/state.mjs browser/root-init.mjs browser/upload-states.mjs browser/number.mjs browser/card-stretch.mjs browser/text-override.mjs browser/control-heights.mjs browser/cfl-multi.mjs browser/crowding.mjs",
96
96
  "prepack": "node tokens/build.mjs",
97
97
  "version": "node tokens/build.mjs && git add dist",
98
98
  "typecheck:react": "tsc -p adapters/react/tsconfig.json --noEmit"
@@ -6,6 +6,25 @@
6
6
  .fdy-badge--info{color:var(--color-info-strong);background:var(--color-info-soft);border-color:color-mix(in srgb,var(--color-info) 26%,transparent);}
7
7
  .fdy-badge--outline{background:transparent;border-color:var(--color-border-strong);color:var(--color-text-muted);box-shadow:none;}
8
8
 
9
+ /* Categorical tone badges — a status vocabulary larger than the semantic palette, from the
10
+ * general --tone-1..8 tokens. Same validated AA formula as .fdy-avatar--tone-* and
11
+ * .fdy-chip--tone-* (text >=4.5:1 both themes, gated by test/contrast.test.mjs).
12
+ *
13
+ * Semantics come first: a state that IS good, bad or waiting takes --success / --danger /
14
+ * --warning. These are for the rest — the states a workflow distinguishes but a palette of five
15
+ * cannot. A back-office document list carrying Draft, Submitted, Approved, Completed, Settled,
16
+ * Closed, Transferred, InDeclaration, Open and Rejected in ONE column collapsed to three colours,
17
+ * which is the report this shipped for. */
18
+ .fdy-badge--tone-1,.fdy-badge--tone-2,.fdy-badge--tone-3,.fdy-badge--tone-4,.fdy-badge--tone-5,.fdy-badge--tone-6,.fdy-badge--tone-7,.fdy-badge--tone-8{background:color-mix(in srgb,var(--_fdy-badge-tone) 18%,var(--color-surface));color:color-mix(in srgb,var(--_fdy-badge-tone) 50%,var(--color-text));border-color:color-mix(in srgb,var(--_fdy-badge-tone) 26%,transparent);}
19
+ .fdy-badge--tone-1{--_fdy-badge-tone:var(--tone-1);}
20
+ .fdy-badge--tone-2{--_fdy-badge-tone:var(--tone-2);}
21
+ .fdy-badge--tone-3{--_fdy-badge-tone:var(--tone-3);}
22
+ .fdy-badge--tone-4{--_fdy-badge-tone:var(--tone-4);}
23
+ .fdy-badge--tone-5{--_fdy-badge-tone:var(--tone-5);}
24
+ .fdy-badge--tone-6{--_fdy-badge-tone:var(--tone-6);}
25
+ .fdy-badge--tone-7{--_fdy-badge-tone:var(--tone-7);}
26
+ .fdy-badge--tone-8{--_fdy-badge-tone:var(--tone-8);}
27
+
9
28
  /* Overlay badge — anchors a small count/dot/icon badge to a corner of any element
10
29
  * (icon, button, text). Wrap the content in .fdy-badge-wrap; add .fdy-badge-ov as a
11
30
  * sibling. Default is a solid neutral pill; colour + dot + position via modifiers. */
@@ -51,6 +51,18 @@
51
51
  .fdy-stat__value{font-family:var(--font-display);font-size:var(--text-3xl);font-weight:var(--weight-bold);letter-spacing:var(--tracking-tighter);line-height:1;color:var(--color-text);font-variant-numeric:tabular-nums;}
52
52
  .fdy-stat__value small{font-size:var(--text-lg);font-weight:var(--weight-semibold);color:var(--color-text-muted);}
53
53
  .fdy-stat__meta{font-size:var(--text-sm);color:var(--color-text-muted);display:flex;align-items:center;gap:var(--space-2);}
54
+ /* A stat value is display type sized for a COUNT — "1,284" — and a back office puts money in it.
55
+ "IDR 300,000.00" needs 224px at --text-3xl and the grid's own track is 11rem, so it wrapped
56
+ between the currency and the number: two lines of 31px where the design says one. Measured, not
57
+ guessed (#020).
58
+ The value shrinks only when its own column is too narrow to hold it, so a wide dashboard keeps
59
+ exactly the type it has today. Scoped to a stat INSIDE .fdy-stats, where the width comes from the
60
+ grid track — `container-type:inline-size` on a standalone .fdy-stat would stop it sizing to its
61
+ own content. The unconditional rule above stays as the fallback wherever @container is missing. */
62
+ @supports (container-type:inline-size){
63
+ .fdy-stats>.fdy-stat{container-type:inline-size;}
64
+ .fdy-stats>.fdy-stat .fdy-stat__value{font-size:clamp(var(--text-xl),11cqw,var(--text-3xl));}
65
+ }
54
66
  .fdy-stats--boxed{background:var(--color-surface);border:var(--bw) solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-1);gap:0;}
55
67
  .fdy-stats--boxed .fdy-stat{padding:var(--space-5);border-right:var(--bw) solid var(--color-border-muted);}
56
68
  .fdy-stats--boxed .fdy-stat:last-child{border-right:0;}
@@ -16,7 +16,12 @@
16
16
  .fdy-dropzone__text{display:flex;flex-direction:column;gap:var(--space-1);}
17
17
 
18
18
  /* File rows (list of added/uploaded/rejected files) */
19
- .fdy-filelist{display:flex;flex-direction:column;gap:var(--space-2);margin-top:var(--space-3);}
19
+ /* Symmetric on purpose. The list carried margin-top and nothing below, so whatever follows it —
20
+ an "Add files" button, in every upload UI there is — sat flush against the last row: measured
21
+ 0px. A block that claims space on one side only is not spacing, it is a lean. */
22
+ .fdy-filelist{display:flex;flex-direction:column;gap:var(--space-2);margin-top:var(--space-3);margin-bottom:var(--space-3);}
23
+ /* Nothing after it, nothing to separate from — so the room is not spent. */
24
+ .fdy-filelist:last-child{margin-bottom:0;}
20
25
  /* Side-by-side rows on wide screens (reflow to one column when narrow). */
21
26
  .fdy-filelist--grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));}
22
27
  .fdy-file{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3);border:var(--bw) solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);}
@@ -128,3 +128,10 @@
128
128
  .fdy-table-bulkbar__count{font-weight:var(--weight-semibold);white-space:nowrap;}
129
129
  .fdy-table-bulkbar__spacer{flex:1;}
130
130
  .fdy-table-bulkbar__actions{display:flex;gap:var(--space-2);}
131
+
132
+ /* Controls inside a data row. `.fdy-input` and friends are width:100%, which in an auto-layout
133
+ table means they contribute NO intrinsic width — the column shrinks to whatever the header text
134
+ needs and the control collapses with it. A NOTE column ends up a box too narrow to read what you
135
+ typed into it. The floor is per-control rather than on the column, because the table does not
136
+ know which of its columns hold controls. */
137
+ .fdy-table td>.fdy-input,.fdy-table td>.fdy-textarea,.fdy-table td>.fdy-combo,.fdy-table td>.fdy-input-group,.fdy-table td>.fdy-datepicker,.fdy-table td>.fdy-timepicker{min-width:7rem;}