@fieldia/widgets 0.12.0 → 0.13.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 (83) hide show
  1. package/package.json +2 -2
  2. package/src/lib/choice-tags.js +4 -2
  3. package/src/lib/choice-tags.js.map +1 -1
  4. package/src/lib/choice-tags.mjs +4 -2
  5. package/src/lib/choice-tags.mjs.map +1 -1
  6. package/src/lib/float.d.mts +14 -0
  7. package/src/lib/float.d.ts +14 -0
  8. package/src/lib/float.js +91 -0
  9. package/src/lib/float.js.map +1 -0
  10. package/src/lib/float.mjs +88 -0
  11. package/src/lib/float.mjs.map +1 -0
  12. package/src/lib/labels.d.mts +2 -0
  13. package/src/lib/labels.d.ts +2 -0
  14. package/src/lib/labels.js +1 -0
  15. package/src/lib/labels.js.map +1 -1
  16. package/src/lib/labels.mjs +1 -0
  17. package/src/lib/labels.mjs.map +1 -1
  18. package/src/lib/layout-styles.d.mts +1 -1
  19. package/src/lib/layout-styles.d.ts +1 -1
  20. package/src/lib/layout-styles.js +12 -5
  21. package/src/lib/layout-styles.js.map +1 -1
  22. package/src/lib/layout-styles.mjs +12 -5
  23. package/src/lib/layout-styles.mjs.map +1 -1
  24. package/src/lib/lines.js +121 -10
  25. package/src/lib/lines.js.map +1 -1
  26. package/src/lib/lines.mjs +121 -10
  27. package/src/lib/lines.mjs.map +1 -1
  28. package/src/lib/locales/ar.js +1 -0
  29. package/src/lib/locales/ar.js.map +1 -1
  30. package/src/lib/locales/ar.mjs +1 -0
  31. package/src/lib/locales/ar.mjs.map +1 -1
  32. package/src/lib/locales/de.js +1 -0
  33. package/src/lib/locales/de.js.map +1 -1
  34. package/src/lib/locales/de.mjs +1 -0
  35. package/src/lib/locales/de.mjs.map +1 -1
  36. package/src/lib/locales/fr.js +1 -0
  37. package/src/lib/locales/fr.js.map +1 -1
  38. package/src/lib/locales/fr.mjs +1 -0
  39. package/src/lib/locales/fr.mjs.map +1 -1
  40. package/src/lib/numbers.d.mts +5 -1
  41. package/src/lib/numbers.d.ts +5 -1
  42. package/src/lib/numbers.js +15 -2
  43. package/src/lib/numbers.js.map +1 -1
  44. package/src/lib/numbers.mjs +13 -2
  45. package/src/lib/numbers.mjs.map +1 -1
  46. package/src/lib/relations.js +11 -2
  47. package/src/lib/relations.js.map +1 -1
  48. package/src/lib/relations.mjs +11 -2
  49. package/src/lib/relations.mjs.map +1 -1
  50. package/src/lib/styles-business.d.mts +1 -1
  51. package/src/lib/styles-business.d.ts +1 -1
  52. package/src/lib/styles-business.js +1 -1
  53. package/src/lib/styles-business.mjs +1 -1
  54. package/src/lib/styles-inputs.d.mts +1 -1
  55. package/src/lib/styles-inputs.d.ts +1 -1
  56. package/src/lib/styles-inputs.js +2 -0
  57. package/src/lib/styles-inputs.js.map +1 -1
  58. package/src/lib/styles-inputs.mjs +2 -0
  59. package/src/lib/styles-inputs.mjs.map +1 -1
  60. package/src/lib/styles-kinds.d.mts +1 -1
  61. package/src/lib/styles-kinds.d.ts +1 -1
  62. package/src/lib/styles-kinds.js +1 -1
  63. package/src/lib/styles-kinds.mjs +1 -1
  64. package/src/lib/styles-sheet.d.mts +1 -1
  65. package/src/lib/styles-sheet.d.ts +1 -1
  66. package/src/lib/styles-sheet.js +28 -12
  67. package/src/lib/styles-sheet.js.map +1 -1
  68. package/src/lib/styles-sheet.mjs +28 -12
  69. package/src/lib/styles-sheet.mjs.map +1 -1
  70. package/src/lib/styles.js +83 -19
  71. package/src/lib/styles.js.map +1 -1
  72. package/src/lib/styles.mjs +83 -19
  73. package/src/lib/styles.mjs.map +1 -1
  74. package/src/lib/themes.d.mts +29 -0
  75. package/src/lib/themes.d.ts +29 -0
  76. package/src/lib/themes.js +180 -0
  77. package/src/lib/themes.js.map +1 -0
  78. package/src/lib/themes.mjs +177 -0
  79. package/src/lib/themes.mjs.map +1 -0
  80. package/src/lib/widgets.js +26 -5
  81. package/src/lib/widgets.js.map +1 -1
  82. package/src/lib/widgets.mjs +27 -6
  83. package/src/lib/widgets.mjs.map +1 -1
package/src/lib/styles.js CHANGED
@@ -22,6 +22,7 @@ const styles_business_1 = require("./styles-business");
22
22
  * form mirrors without a second stylesheet.
23
23
  */
24
24
  const layout_styles_1 = require("./layout-styles");
25
+ const themes_1 = require("./themes");
25
26
  /**
26
27
  * The widths of a form at which its groups take their medium and their narrow
27
28
  * columns: up to 760px and up to 520px of the form's own width, as the
@@ -31,8 +32,11 @@ const layout_styles_1 = require("./layout-styles");
31
32
  exports.FORM_WIDTHS = { medium: 760, narrow: 520 };
32
33
  /** The skins and the parts' chrome. One literal, so the script bundle can minify it as CSS. */
33
34
  const SKINS_CSS = /* css */ `
34
- /* .fd-theme carries the same tokens for things outside a form, such as a dialog over the page. One inside a form
35
+ /* Fieldia's tokens (its colours, sizes and fonts) live in a cascade layer: a host's own rule, of any weight, sets
36
+ them over Fieldia's, whole. The skins, themes, page looks and schemes keep their order inside it.
37
+ .fd-theme carries the same tokens for things outside a form, such as a dialog over the page. One inside a form
35
38
  with no skin of its own (the conversation beside a record) wears the form's skin and scheme instead. */
39
+ @layer fieldia-tokens {
36
40
  .fd-form, .fd-theme:is([data-fd-skin], :not(.fd-form *)) {
37
41
  --fd-font: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Noto Sans Arabic", sans-serif;
38
42
  --fd-text: #212529;
@@ -62,12 +66,6 @@ const SKINS_CSS = /* css */ `
62
66
  --fd-label-weight: 600;
63
67
  --fd-gap-x: 32px;
64
68
  --fd-gap-y: 14px;
65
- container-type: inline-size;
66
- font-family: var(--fd-font);
67
- font-size: 14px;
68
- line-height: 1.45;
69
- color: var(--fd-text);
70
- -webkit-text-size-adjust: 100%;
71
69
  }
72
70
  /* Ant Design's blue and red, a shade darker: words in them read at 4.5:1 (WCAG AA) on white, the page and their soft shades. */
73
71
  .fd-form[data-fd-skin="outlined"], .fd-theme[data-fd-skin="outlined"] {
@@ -91,6 +89,15 @@ const SKINS_CSS = /* css */ `
91
89
  --fd-gap-x: 24px;
92
90
  --fd-gap-y: 18px;
93
91
  }
92
+ }
93
+ .fd-form, .fd-theme:is([data-fd-skin], :not(.fd-form *)) {
94
+ container-type: inline-size;
95
+ font-family: var(--fd-font);
96
+ font-size: 14px;
97
+ line-height: 1.45;
98
+ color: var(--fd-text);
99
+ -webkit-text-size-adjust: 100%;
100
+ }
94
101
  .fd-form *, .fd-form *::before, .fd-form *::after { box-sizing: border-box; }
95
102
  .fd-form [hidden] { display: none !important; }
96
103
 
@@ -132,16 +139,24 @@ const SKINS_CSS = /* css */ `
132
139
  .fd-label { font-weight: var(--fd-label-weight); color: var(--fd-text); }
133
140
  /* The ✓ of a field filled in right, by its label. */
134
141
  .fd-valid-mark { color: var(--fd-success); width: 1em; height: 1em; margin-inline-start: 6px; vertical-align: -0.15em; stroke-width: 2.4; }
135
- .fd-field.fd-required > .fd-label::after { content: " *"; color: var(--fd-error); }
136
- .fd-form[data-fd-skin="outlined"] .fd-field.fd-required > .fd-label::after { content: ""; }
137
- .fd-form[data-fd-skin="outlined"] .fd-field.fd-required > .fd-label::before { content: "* "; color: var(--fd-error); }
142
+ /* No space between the star and the label's last word, its gap a margin: a line never breaks before it. */
143
+ .fd-field.fd-required > .fd-label::after { content: "*"; margin-inline-start: 0.25em; color: var(--fd-error); }
144
+ .fd-form[data-fd-skin="outlined"] .fd-field.fd-required > .fd-label::after { content: none; }
145
+ .fd-form[data-fd-skin="outlined"] .fd-field.fd-required > .fd-label::before { content: "*"; margin-inline-end: 0.25em; color: var(--fd-error); }
138
146
  .fd-help { color: var(--fd-muted); font-size: 12.5px; }
139
147
  /* A field's help behind a (?) by its label: a bubble on hover, focus or a tap. */
140
148
  .fd-help-tip-wrap { position: relative; display: inline-flex; vertical-align: 0.05em; margin-inline-start: 6px; }
149
+ /* In a label it stands just after the last word, out of the line's flow: a browser may always break a line
150
+ before a box such as the (?), no-break space or not, and it would wrap onto a line of its own.
151
+ The label keeps room for it at its end, and a required star moves past it. */
152
+ .fd-label > .fd-help-tip-wrap { position: absolute; margin-block-start: 0.15em; }
153
+ .fd-label:has(> .fd-help-tip-wrap) { padding-inline-end: 22px; }
154
+ .fd-field.fd-required > .fd-label:has(> .fd-help-tip-wrap)::after { padding-inline-start: 22px; }
155
+ .fd-form:not([data-fd-skin="outlined"]) .fd-field.fd-required > .fd-label:has(> .fd-help-tip-wrap) { padding-inline-end: 0; }
141
156
  .fd-help-tip { all: unset; box-sizing: border-box; display: inline-grid; place-items: center; width: 16px; height: 16px; border: 1px solid var(--fd-border); border-radius: 50%; color: var(--fd-muted); font-size: 11px; font-weight: 600; line-height: 1; cursor: help; }
142
157
  .fd-help-tip:hover, .fd-help-tip[aria-expanded="true"] { color: var(--fd-accent); border-color: var(--fd-accent); }
143
158
  .fd-help-tip:focus-visible { outline: 2px solid var(--fd-focus); outline-offset: 2px; }
144
- .fd-help-bubble { position: absolute; inset-block-start: calc(100% + 6px); inset-inline-start: -8px; z-index: 30; width: max-content; max-width: min(280px, 70vw); padding: 6px 9px; border-radius: 6px; background: var(--fd-text); color: var(--fd-surface); font-size: 12.5px; font-weight: 400; line-height: 1.4; white-space: normal; box-shadow: 0 6px 18px rgb(0 0 0 / 0.18); }
159
+ .fd-help-bubble { position: absolute; inset-block-start: calc(100% + 6px); inset-inline-start: -8px; z-index: 30; width: max-content; max-width: min(280px, calc(100vw - 16px)); padding: 6px 9px; border-radius: 6px; background: var(--fd-text); color: var(--fd-surface); font-size: 12.5px; font-weight: 400; line-height: 1.4; white-space: normal; box-shadow: 0 6px 18px rgb(0 0 0 / 0.18); }
145
160
  /*
146
161
  * A page's words run the way they are written — a sentence left in English on
147
162
  * an Arabic page keeps its full stop at its end — and line up with the form.
@@ -162,9 +177,12 @@ const SKINS_CSS = /* css */ `
162
177
  /* One label width for every field, so a field spanning two columns lines up with its neighbours. */
163
178
  grid-template-columns: var(--fd-label-width, 11em) minmax(0, 1fr);
164
179
  column-gap: 12px;
165
- align-items: baseline;
166
180
  }
167
- .fd-form[data-fd-skin="underline"] .fd-field:where(:not([data-labels])) > .fd-label { grid-column: 1; }
181
+ /* The label at its value's top, its words level with a one-line box's, as labels set beside by a page sit: never
182
+ by the value's baseline, which a box of several lines (a code box, rich text, files) puts at its foot. */
183
+ .fd-form[data-fd-skin="underline"] .fd-field:where(:not([data-labels])) > .fd-label {
184
+ grid-column: 1; align-self: start; padding-block-start: max(0px, calc((var(--fd-control-height, 30px) - 1.45em) / 2));
185
+ }
168
186
  /* A table of lines needs the full width: its label sits above it. */
169
187
  .fd-form[data-fd-skin="underline"] .fd-field[data-type="one2many"] { grid-template-columns: minmax(0, 1fr); }
170
188
  .fd-form[data-fd-skin="underline"] .fd-field[data-type="one2many"] > * { grid-column: 1 !important; }
@@ -216,6 +234,8 @@ const SKINS_CSS = /* css */ `
216
234
  border-radius: var(--fd-control-radius);
217
235
  padding: var(--fd-pad-y) var(--fd-pad-x);
218
236
  min-height: var(--fd-control-height, 30px);
237
+ /* A value longer than its box ends in "…", not cut mid-letter (the whole of it shows on hover). */
238
+ text-overflow: ellipsis;
219
239
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
220
240
  }
221
241
  .fd-input::placeholder { color: var(--fd-muted); opacity: 0.8; }
@@ -225,7 +245,7 @@ const SKINS_CSS = /* css */ `
225
245
  .fd-form[data-fd-skin="underline"] .fd-input:focus { box-shadow: 0 1px 0 0 var(--fd-focus); }
226
246
  .fd-form[data-fd-skin="underline"] .fd-field.fd-required .fd-input { border-color: var(--fd-accent); }
227
247
  .fd-input[readonly] { background: transparent; border-color: transparent; padding-inline: 0; }
228
- .fd-form[data-fd-skin="outlined"] .fd-input[readonly] { background: rgba(0, 0, 0, 0.04); border-color: var(--fd-border); padding-inline: var(--fd-pad-x); color: var(--fd-muted); }
248
+ .fd-form[data-fd-skin="outlined"] .fd-input[readonly] { background: color-mix(in srgb, var(--fd-text) 5%, var(--fd-surface)); border-color: var(--fd-border); padding-inline: var(--fd-pad-x); color: var(--fd-muted); }
229
249
  /* A whole form locked reads as a record: plain values in either skin, no boxes, and no prompts to type. */
230
250
  .fd-form[data-readonly] .fd-input[readonly] { background: transparent; border-color: transparent; padding-inline: 0; color: var(--fd-text); }
231
251
  .fd-form[data-readonly] .fd-input::placeholder { color: transparent; }
@@ -301,6 +321,10 @@ const SKINS_CSS = /* css */ `
301
321
  .fd-combo-clear:hover { color: var(--fd-text); background: var(--fd-page); }
302
322
  /* A link that can be opened has its open button beside the clear button. */
303
323
  .fd-combo:has(> .fd-combo-open:not([hidden])) .fd-combo-input { padding-inline-end: 56px; }
324
+ /* Read-only, its clear button is gone: its words take the room, and an open button moves to the end. */
325
+ .fd-combo:not(.fd-choice-search .fd-combo):has(> .fd-combo-clear[hidden]) .fd-combo-input[readonly] { padding-inline-end: var(--fd-pad-x); }
326
+ .fd-combo:not(.fd-choice-search .fd-combo):has(> .fd-combo-clear[hidden]):has(> .fd-combo-open:not([hidden])) .fd-combo-input[readonly] { padding-inline-end: 30px; }
327
+ .fd-combo:has(> .fd-combo-input[readonly]) > .fd-combo-clear[hidden] ~ .fd-combo-open { inset-inline-end: 3px; }
304
328
  .fd-combo-open {
305
329
  position: absolute; inset-inline-end: 29px; border: none; background: none; cursor: pointer; color: var(--fd-accent);
306
330
  font-size: 14px; line-height: 1; padding: 0 4px; border-radius: 4px; min-width: 24px; min-height: 24px; display: inline-grid; place-items: center;
@@ -341,7 +365,37 @@ button.fd-chip-label:hover { text-decoration: underline; }
341
365
  /* A yes/no cell sits level with the inputs beside it. */
342
366
  .fd-lines-table td > .fd-checkbox, .fd-lines-table td > .fd-switch { margin-block-start: 6px; }
343
367
  .fd-lines-table .fd-lines-grip { width: 1px; min-width: 0; padding-inline: 6px 2px; }
368
+ /* A table wider than its box scrolls sideways under a line's grip and its delete button, which stay at its ends. */
369
+ .fd-lines:not([data-cards="always"]) .fd-lines-table :is(th, td):is(.fd-lines-grip, .fd-lines-tools) { position: sticky; z-index: 1; background-color: var(--fd-surface); }
370
+ .fd-lines:not([data-cards="always"]) .fd-lines-table :is(th, td).fd-lines-grip { inset-inline-start: 0; }
371
+ .fd-lines:not([data-cards="always"]) .fd-lines-table :is(th, td).fd-lines-tools { inset-inline-end: 0; }
372
+ /* A column of yes/no, numbers, money or dates as wide as its values, as Flectra's lists size them: words and links have the rest. */
373
+ .fd-lines-table td[data-fit] { min-width: 0; }
374
+ /* A head may take two lines rather than widen a column of short values: "Delivery Lead Time" over "45". */
375
+ .fd-lines-table thead th:not(.fd-lines-grip, .fd-lines-tools) { white-space: normal; }
376
+ .fd-lines-table thead th { vertical-align: bottom; }
377
+ .fd-lines-table th[data-fit="boolean"] { width: 5em; min-width: 5em; }
378
+ .fd-lines-table th[data-fit="integer"] { width: max(7em, var(--fd-fit-need, 0px)); min-width: max(7em, var(--fd-fit-need, 0px)); }
379
+ .fd-lines-table th[data-fit="float"] { width: max(7.5em, var(--fd-fit-need, 0px)); min-width: max(7.5em, var(--fd-fit-need, 0px)); }
380
+ .fd-lines-table th[data-fit="monetary"] { width: max(11.5em, var(--fd-fit-need, 0px)); min-width: max(11.5em, var(--fd-fit-need, 0px)); }
381
+ .fd-lines-table th[data-fit="date"] { width: 9em; min-width: 9em; }
382
+ .fd-lines-table th[data-fit="datetime"] { width: 12.5em; min-width: 12.5em; }
383
+ /* Numbers and money read from the end, as Flectra's lists align them. */
384
+ .fd-lines-table th:is([data-fit="integer"], [data-fit="float"], [data-fit="monetary"]) { text-align: end; }
385
+ .fd-lines-table td:is([data-fit="integer"], [data-fit="float"], [data-fit="monetary"]) input { text-align: end; }
386
+ /* A table reads as a table, as a grid does: a line shows its boxes and buttons where the pointer or the cursor is.
387
+ Only colours and visibility change, never a size: a line left for a click elsewhere must not move what is clicked.
388
+ A touch screen has no pointer to hover with: there the boxes always show. */
389
+ @media (hover: hover) and (pointer: fine) {
390
+ .fd-lines:not([data-cards="always"]) .fd-lines-table tbody tr:not(:hover, :focus-within) .fd-input:not([aria-invalid="true"]) { border-color: transparent; background-color: transparent; box-shadow: none; }
391
+ .fd-lines:not([data-cards="always"]) .fd-lines-table tbody tr:not(:hover, :focus-within) :is(.fd-combo-open, .fd-combo-clear) { visibility: hidden; }
392
+ }
344
393
  .fd-line-grip { display: block; margin-block-start: 7px; cursor: grab; }
394
+ /* A line dragged by its grip follows the pointer, lifted over the others, which slide out of its way. */
395
+ .fd-lines-dragging, .fd-lines-dragging * { cursor: grabbing; user-select: none; }
396
+ .fd-lines-dragging > tr:not(.fd-line-lifted) { transition: transform 0.15s ease; }
397
+ .fd-line-lifted { position: relative; z-index: 2; box-shadow: 0 6px 18px rgba(15, 20, 25, 0.16); }
398
+ .fd-line-lifted > td { background: var(--fd-surface); }
345
399
  .fd-line-delete { border: none; background: none; cursor: pointer; color: var(--fd-muted); font-size: 16px; line-height: 1; padding: 4px 6px; border-radius: 4px; min-width: 24px; min-height: 24px; }
346
400
  .fd-line-delete:hover { color: var(--fd-error); background: var(--fd-error-soft); }
347
401
  /* A table's own rules: a line's or a cell's tone and bold (Flectra's decoration-*), and buttons on a line. */
@@ -592,7 +646,8 @@ button.fd-chip-label:hover { text-decoration: underline; }
592
646
  .fd-button-primary { background: var(--fd-accent); border-color: var(--fd-accent); color: var(--fd-accent-text); }
593
647
  .fd-button-primary:hover { color: var(--fd-accent-text); filter: brightness(1.12); }
594
648
  .fd-button-danger { color: var(--fd-error); border-color: var(--fd-error); }
595
- .fd-button-danger:hover { background: var(--fd-error); color: #fff; }
649
+ /* The surface's colour on the error's: white on a light page's deep red, near-black on a dark page's coral. */
650
+ .fd-button-danger:hover { background: var(--fd-error); color: var(--fd-surface); }
596
651
  .fd-button-link { border-color: transparent; background: none; color: var(--fd-accent); padding-inline: 4px; }
597
652
  .fd-form[data-fd-skin="underline"] .fd-button { border-radius: 3px; }
598
653
  .fd-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
@@ -624,9 +679,13 @@ button.fd-chip-label:hover { text-decoration: underline; }
624
679
  .fd-sheet-layout { align-items: start; }
625
680
  /* Save and Discard closing the sheet, when the page puts them at its foot. */
626
681
  .fd-sheet-foot { margin: 4px -28px -28px; padding: 12px 28px; border-block-start: 1px solid var(--fd-border); border-end-start-radius: inherit; border-end-end-radius: inherit; }
627
- .fd-sheet-layout.fd-has-side { grid-template-columns: minmax(0, 1fr) minmax(260px, 360px); }
628
- /* The side panel goes under the sheet before the sheet is left too narrow for a label beside its value. */
629
- @container (max-width: 1000px) { .fd-sheet-layout.fd-has-side { grid-template-columns: minmax(0, 1fr); } }
682
+ /* The side panel under the sheet, the sheet taking the whole width; beside it, as Flectra's chatter, on a form of
683
+ 1534px or more — the page growing by the panel's width, so the sheet keeps its own ("none" plus a width is no
684
+ width: a full page stays full). A page that asks keeps it beside down to 600px (record-styles). */
685
+ @container (min-width: 1534px) {
686
+ .fd-sheet-layout.fd-has-side { grid-template-columns: minmax(0, 1fr) minmax(260px, 360px); max-width: calc(var(--fd-page-max, 1180px) + 376px); }
687
+ }
688
+ .fd-sheet-layout.fd-has-side[data-side-beside="always"] { grid-template-columns: minmax(0, 1fr) minmax(260px, 360px); }
630
689
  /* A part hidden at some widths of the form (hideOn): narrow up to 520px, medium up to 760px, wide above — the form's own width, as its columns. */
631
690
  .fd-form { container-name: fd-form; }
632
691
  @container fd-form (max-width: 520px) { .fd-form [data-hide-on~="narrow"] { display: none !important; } }
@@ -766,6 +825,9 @@ button.fd-chip-label:hover { text-decoration: underline; }
766
825
  .fd-property { display: grid; grid-template-columns: minmax(120px, 30%) minmax(0, 1fr); align-items: center; gap: 12px; min-width: 0; }
767
826
  .fd-property > label { color: var(--fd-muted); font-size: 13px; }
768
827
  .fd-property[data-type="boolean"] > :last-child { justify-self: start; }
828
+ /* Beside their values, as the sheet's labels are: the same label column, the same words, the same gap between halves — the properties read as fields of the sheet. */
829
+ .fd-form[data-fd-skin="underline"] .fd-property { grid-template-columns: var(--fd-label-width, 11em) minmax(0, 1fr); }
830
+ .fd-form[data-fd-skin="underline"] .fd-property > label { color: var(--fd-text); font-size: inherit; font-weight: var(--fd-label-weight); }
769
831
  @container (max-width: 520px) { .fd-property { grid-template-columns: minmax(0, 1fr); gap: 4px; } }
770
832
  .fd-progressbar {
771
833
  position: relative; height: 22px; min-width: 120px; border-radius: 999px; overflow: hidden;
@@ -952,7 +1014,9 @@ button.fd-chip-label:hover { text-decoration: underline; }
952
1014
  @media (prefers-reduced-motion: reduce) { .fd-form *, .fd-form *::before, .fd-form *::after { transition: none !important; } .fd-button[aria-busy="true"]::after { animation: none; } }
953
1015
  `;
954
1016
  /** Fieldia's whole stylesheet: the skins, then the layout over them, the inputs' details, the question kinds and the choices' details. */
955
- exports.FIELDIA_CSS = SKINS_CSS + layout_styles_1.LAYOUT_CSS + styles_inputs_1.INPUTS_CSS + styles_sheet_1.SHEET_CSS + styles_business_1.BUSINESS_CSS + styles_kinds_1.KINDS_CSS + styles_choices_1.CHOICES_CSS + styles_parts_1.PARTS_CSS;
1017
+ // Themes' tokens after the skins' and before the page's look; their own shapes after the parts they reshape, and
1018
+ // before the page's own looks for each kind of part, which win over a theme as the page's look does.
1019
+ exports.FIELDIA_CSS = SKINS_CSS + themes_1.THEME_TOKENS_CSS + layout_styles_1.LAYOUT_CSS + styles_inputs_1.INPUTS_CSS + styles_sheet_1.SHEET_CSS + styles_business_1.BUSINESS_CSS + themes_1.THEME_RULES_CSS + styles_kinds_1.KINDS_CSS + styles_choices_1.CHOICES_CSS + styles_parts_1.PARTS_CSS;
956
1020
  const STYLE_ID = 'fieldia-styles';
957
1021
  /** Add Fieldia's stylesheet to a document, once. */
958
1022
  function installStyles(document) {
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/styles.ts"],"names":[],"mappings":";;;AA+7BA,sCAMC;AAr8BD,iDAA2C;AAC3C,qDAA+C;AAC/C,mDAA6C;AAC7C,iDAA2C;AAC3C,iDAA2C;AAC3C,uDAAiD;AAEjD;;;;;;;;;;;;GAYG;AACH,mDAA6C;AAE7C;;;;;GAKG;AACU,QAAA,WAAW,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAW,CAAC;AAEjE,+FAA+F;AAC/F,MAAM,SAAS,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAw5B3B,CAAC;AAEF,0IAA0I;AAC7H,QAAA,WAAW,GAAG,SAAS,GAAG,0BAAU,GAAG,0BAAU,GAAG,wBAAS,GAAG,8BAAY,GAAG,wBAAS,GAAG,4BAAW,GAAG,wBAAS,CAAC;AAEhI,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAElC,oDAAoD;AACpD,SAAgB,aAAa,CAAC,QAAkB;IAC9C,IAAI,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC;QAAE,OAAO;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC;IACpB,KAAK,CAAC,WAAW,GAAG,mBAAW,CAAC;IAChC,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC"}
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/styles.ts"],"names":[],"mappings":";;;AA+/BA,sCAMC;AArgCD,iDAA2C;AAC3C,qDAA+C;AAC/C,mDAA6C;AAC7C,iDAA2C;AAC3C,iDAA2C;AAC3C,uDAAiD;AAEjD;;;;;;;;;;;;GAYG;AACH,mDAA6C;AAC7C,qCAA6D;AAE7D;;;;;GAKG;AACU,QAAA,WAAW,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAW,CAAC;AAEjE,+FAA+F;AAC/F,MAAM,SAAS,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAq9B3B,CAAC;AAEF,0IAA0I;AAC1I,iHAAiH;AACjH,qGAAqG;AACxF,QAAA,WAAW,GAAG,SAAS,GAAG,yBAAgB,GAAG,0BAAU,GAAG,0BAAU,GAAG,wBAAS,GAAG,8BAAY,GAAG,wBAAe,GAAG,wBAAS,GAAG,4BAAW,GAAG,wBAAS,CAAC;AAErK,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAElC,oDAAoD;AACpD,SAAgB,aAAa,CAAC,QAAkB;IAC9C,IAAI,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC;QAAE,OAAO;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC;IACpB,KAAK,CAAC,WAAW,GAAG,mBAAW,CAAC;IAChC,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC"}
@@ -18,6 +18,7 @@ import { BUSINESS_CSS } from './styles-business.mjs';
18
18
  * form mirrors without a second stylesheet.
19
19
  */
20
20
  import { LAYOUT_CSS } from './layout-styles.mjs';
21
+ import { THEME_RULES_CSS, THEME_TOKENS_CSS } from './themes.mjs';
21
22
  /**
22
23
  * The widths of a form at which its groups take their medium and their narrow
23
24
  * columns: up to 760px and up to 520px of the form's own width, as the
@@ -27,8 +28,11 @@ import { LAYOUT_CSS } from './layout-styles.mjs';
27
28
  export const FORM_WIDTHS = { medium: 760, narrow: 520 };
28
29
  /** The skins and the parts' chrome. One literal, so the script bundle can minify it as CSS. */
29
30
  const SKINS_CSS = /* css */ `
30
- /* .fd-theme carries the same tokens for things outside a form, such as a dialog over the page. One inside a form
31
+ /* Fieldia's tokens (its colours, sizes and fonts) live in a cascade layer: a host's own rule, of any weight, sets
32
+ them over Fieldia's, whole. The skins, themes, page looks and schemes keep their order inside it.
33
+ .fd-theme carries the same tokens for things outside a form, such as a dialog over the page. One inside a form
31
34
  with no skin of its own (the conversation beside a record) wears the form's skin and scheme instead. */
35
+ @layer fieldia-tokens {
32
36
  .fd-form, .fd-theme:is([data-fd-skin], :not(.fd-form *)) {
33
37
  --fd-font: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Noto Sans Arabic", sans-serif;
34
38
  --fd-text: #212529;
@@ -58,12 +62,6 @@ const SKINS_CSS = /* css */ `
58
62
  --fd-label-weight: 600;
59
63
  --fd-gap-x: 32px;
60
64
  --fd-gap-y: 14px;
61
- container-type: inline-size;
62
- font-family: var(--fd-font);
63
- font-size: 14px;
64
- line-height: 1.45;
65
- color: var(--fd-text);
66
- -webkit-text-size-adjust: 100%;
67
65
  }
68
66
  /* Ant Design's blue and red, a shade darker: words in them read at 4.5:1 (WCAG AA) on white, the page and their soft shades. */
69
67
  .fd-form[data-fd-skin="outlined"], .fd-theme[data-fd-skin="outlined"] {
@@ -87,6 +85,15 @@ const SKINS_CSS = /* css */ `
87
85
  --fd-gap-x: 24px;
88
86
  --fd-gap-y: 18px;
89
87
  }
88
+ }
89
+ .fd-form, .fd-theme:is([data-fd-skin], :not(.fd-form *)) {
90
+ container-type: inline-size;
91
+ font-family: var(--fd-font);
92
+ font-size: 14px;
93
+ line-height: 1.45;
94
+ color: var(--fd-text);
95
+ -webkit-text-size-adjust: 100%;
96
+ }
90
97
  .fd-form *, .fd-form *::before, .fd-form *::after { box-sizing: border-box; }
91
98
  .fd-form [hidden] { display: none !important; }
92
99
 
@@ -128,16 +135,24 @@ const SKINS_CSS = /* css */ `
128
135
  .fd-label { font-weight: var(--fd-label-weight); color: var(--fd-text); }
129
136
  /* The ✓ of a field filled in right, by its label. */
130
137
  .fd-valid-mark { color: var(--fd-success); width: 1em; height: 1em; margin-inline-start: 6px; vertical-align: -0.15em; stroke-width: 2.4; }
131
- .fd-field.fd-required > .fd-label::after { content: " *"; color: var(--fd-error); }
132
- .fd-form[data-fd-skin="outlined"] .fd-field.fd-required > .fd-label::after { content: ""; }
133
- .fd-form[data-fd-skin="outlined"] .fd-field.fd-required > .fd-label::before { content: "* "; color: var(--fd-error); }
138
+ /* No space between the star and the label's last word, its gap a margin: a line never breaks before it. */
139
+ .fd-field.fd-required > .fd-label::after { content: "*"; margin-inline-start: 0.25em; color: var(--fd-error); }
140
+ .fd-form[data-fd-skin="outlined"] .fd-field.fd-required > .fd-label::after { content: none; }
141
+ .fd-form[data-fd-skin="outlined"] .fd-field.fd-required > .fd-label::before { content: "*"; margin-inline-end: 0.25em; color: var(--fd-error); }
134
142
  .fd-help { color: var(--fd-muted); font-size: 12.5px; }
135
143
  /* A field's help behind a (?) by its label: a bubble on hover, focus or a tap. */
136
144
  .fd-help-tip-wrap { position: relative; display: inline-flex; vertical-align: 0.05em; margin-inline-start: 6px; }
145
+ /* In a label it stands just after the last word, out of the line's flow: a browser may always break a line
146
+ before a box such as the (?), no-break space or not, and it would wrap onto a line of its own.
147
+ The label keeps room for it at its end, and a required star moves past it. */
148
+ .fd-label > .fd-help-tip-wrap { position: absolute; margin-block-start: 0.15em; }
149
+ .fd-label:has(> .fd-help-tip-wrap) { padding-inline-end: 22px; }
150
+ .fd-field.fd-required > .fd-label:has(> .fd-help-tip-wrap)::after { padding-inline-start: 22px; }
151
+ .fd-form:not([data-fd-skin="outlined"]) .fd-field.fd-required > .fd-label:has(> .fd-help-tip-wrap) { padding-inline-end: 0; }
137
152
  .fd-help-tip { all: unset; box-sizing: border-box; display: inline-grid; place-items: center; width: 16px; height: 16px; border: 1px solid var(--fd-border); border-radius: 50%; color: var(--fd-muted); font-size: 11px; font-weight: 600; line-height: 1; cursor: help; }
138
153
  .fd-help-tip:hover, .fd-help-tip[aria-expanded="true"] { color: var(--fd-accent); border-color: var(--fd-accent); }
139
154
  .fd-help-tip:focus-visible { outline: 2px solid var(--fd-focus); outline-offset: 2px; }
140
- .fd-help-bubble { position: absolute; inset-block-start: calc(100% + 6px); inset-inline-start: -8px; z-index: 30; width: max-content; max-width: min(280px, 70vw); padding: 6px 9px; border-radius: 6px; background: var(--fd-text); color: var(--fd-surface); font-size: 12.5px; font-weight: 400; line-height: 1.4; white-space: normal; box-shadow: 0 6px 18px rgb(0 0 0 / 0.18); }
155
+ .fd-help-bubble { position: absolute; inset-block-start: calc(100% + 6px); inset-inline-start: -8px; z-index: 30; width: max-content; max-width: min(280px, calc(100vw - 16px)); padding: 6px 9px; border-radius: 6px; background: var(--fd-text); color: var(--fd-surface); font-size: 12.5px; font-weight: 400; line-height: 1.4; white-space: normal; box-shadow: 0 6px 18px rgb(0 0 0 / 0.18); }
141
156
  /*
142
157
  * A page's words run the way they are written — a sentence left in English on
143
158
  * an Arabic page keeps its full stop at its end — and line up with the form.
@@ -158,9 +173,12 @@ const SKINS_CSS = /* css */ `
158
173
  /* One label width for every field, so a field spanning two columns lines up with its neighbours. */
159
174
  grid-template-columns: var(--fd-label-width, 11em) minmax(0, 1fr);
160
175
  column-gap: 12px;
161
- align-items: baseline;
162
176
  }
163
- .fd-form[data-fd-skin="underline"] .fd-field:where(:not([data-labels])) > .fd-label { grid-column: 1; }
177
+ /* The label at its value's top, its words level with a one-line box's, as labels set beside by a page sit: never
178
+ by the value's baseline, which a box of several lines (a code box, rich text, files) puts at its foot. */
179
+ .fd-form[data-fd-skin="underline"] .fd-field:where(:not([data-labels])) > .fd-label {
180
+ grid-column: 1; align-self: start; padding-block-start: max(0px, calc((var(--fd-control-height, 30px) - 1.45em) / 2));
181
+ }
164
182
  /* A table of lines needs the full width: its label sits above it. */
165
183
  .fd-form[data-fd-skin="underline"] .fd-field[data-type="one2many"] { grid-template-columns: minmax(0, 1fr); }
166
184
  .fd-form[data-fd-skin="underline"] .fd-field[data-type="one2many"] > * { grid-column: 1 !important; }
@@ -212,6 +230,8 @@ const SKINS_CSS = /* css */ `
212
230
  border-radius: var(--fd-control-radius);
213
231
  padding: var(--fd-pad-y) var(--fd-pad-x);
214
232
  min-height: var(--fd-control-height, 30px);
233
+ /* A value longer than its box ends in "…", not cut mid-letter (the whole of it shows on hover). */
234
+ text-overflow: ellipsis;
215
235
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
216
236
  }
217
237
  .fd-input::placeholder { color: var(--fd-muted); opacity: 0.8; }
@@ -221,7 +241,7 @@ const SKINS_CSS = /* css */ `
221
241
  .fd-form[data-fd-skin="underline"] .fd-input:focus { box-shadow: 0 1px 0 0 var(--fd-focus); }
222
242
  .fd-form[data-fd-skin="underline"] .fd-field.fd-required .fd-input { border-color: var(--fd-accent); }
223
243
  .fd-input[readonly] { background: transparent; border-color: transparent; padding-inline: 0; }
224
- .fd-form[data-fd-skin="outlined"] .fd-input[readonly] { background: rgba(0, 0, 0, 0.04); border-color: var(--fd-border); padding-inline: var(--fd-pad-x); color: var(--fd-muted); }
244
+ .fd-form[data-fd-skin="outlined"] .fd-input[readonly] { background: color-mix(in srgb, var(--fd-text) 5%, var(--fd-surface)); border-color: var(--fd-border); padding-inline: var(--fd-pad-x); color: var(--fd-muted); }
225
245
  /* A whole form locked reads as a record: plain values in either skin, no boxes, and no prompts to type. */
226
246
  .fd-form[data-readonly] .fd-input[readonly] { background: transparent; border-color: transparent; padding-inline: 0; color: var(--fd-text); }
227
247
  .fd-form[data-readonly] .fd-input::placeholder { color: transparent; }
@@ -297,6 +317,10 @@ const SKINS_CSS = /* css */ `
297
317
  .fd-combo-clear:hover { color: var(--fd-text); background: var(--fd-page); }
298
318
  /* A link that can be opened has its open button beside the clear button. */
299
319
  .fd-combo:has(> .fd-combo-open:not([hidden])) .fd-combo-input { padding-inline-end: 56px; }
320
+ /* Read-only, its clear button is gone: its words take the room, and an open button moves to the end. */
321
+ .fd-combo:not(.fd-choice-search .fd-combo):has(> .fd-combo-clear[hidden]) .fd-combo-input[readonly] { padding-inline-end: var(--fd-pad-x); }
322
+ .fd-combo:not(.fd-choice-search .fd-combo):has(> .fd-combo-clear[hidden]):has(> .fd-combo-open:not([hidden])) .fd-combo-input[readonly] { padding-inline-end: 30px; }
323
+ .fd-combo:has(> .fd-combo-input[readonly]) > .fd-combo-clear[hidden] ~ .fd-combo-open { inset-inline-end: 3px; }
300
324
  .fd-combo-open {
301
325
  position: absolute; inset-inline-end: 29px; border: none; background: none; cursor: pointer; color: var(--fd-accent);
302
326
  font-size: 14px; line-height: 1; padding: 0 4px; border-radius: 4px; min-width: 24px; min-height: 24px; display: inline-grid; place-items: center;
@@ -337,7 +361,37 @@ button.fd-chip-label:hover { text-decoration: underline; }
337
361
  /* A yes/no cell sits level with the inputs beside it. */
338
362
  .fd-lines-table td > .fd-checkbox, .fd-lines-table td > .fd-switch { margin-block-start: 6px; }
339
363
  .fd-lines-table .fd-lines-grip { width: 1px; min-width: 0; padding-inline: 6px 2px; }
364
+ /* A table wider than its box scrolls sideways under a line's grip and its delete button, which stay at its ends. */
365
+ .fd-lines:not([data-cards="always"]) .fd-lines-table :is(th, td):is(.fd-lines-grip, .fd-lines-tools) { position: sticky; z-index: 1; background-color: var(--fd-surface); }
366
+ .fd-lines:not([data-cards="always"]) .fd-lines-table :is(th, td).fd-lines-grip { inset-inline-start: 0; }
367
+ .fd-lines:not([data-cards="always"]) .fd-lines-table :is(th, td).fd-lines-tools { inset-inline-end: 0; }
368
+ /* A column of yes/no, numbers, money or dates as wide as its values, as Flectra's lists size them: words and links have the rest. */
369
+ .fd-lines-table td[data-fit] { min-width: 0; }
370
+ /* A head may take two lines rather than widen a column of short values: "Delivery Lead Time" over "45". */
371
+ .fd-lines-table thead th:not(.fd-lines-grip, .fd-lines-tools) { white-space: normal; }
372
+ .fd-lines-table thead th { vertical-align: bottom; }
373
+ .fd-lines-table th[data-fit="boolean"] { width: 5em; min-width: 5em; }
374
+ .fd-lines-table th[data-fit="integer"] { width: max(7em, var(--fd-fit-need, 0px)); min-width: max(7em, var(--fd-fit-need, 0px)); }
375
+ .fd-lines-table th[data-fit="float"] { width: max(7.5em, var(--fd-fit-need, 0px)); min-width: max(7.5em, var(--fd-fit-need, 0px)); }
376
+ .fd-lines-table th[data-fit="monetary"] { width: max(11.5em, var(--fd-fit-need, 0px)); min-width: max(11.5em, var(--fd-fit-need, 0px)); }
377
+ .fd-lines-table th[data-fit="date"] { width: 9em; min-width: 9em; }
378
+ .fd-lines-table th[data-fit="datetime"] { width: 12.5em; min-width: 12.5em; }
379
+ /* Numbers and money read from the end, as Flectra's lists align them. */
380
+ .fd-lines-table th:is([data-fit="integer"], [data-fit="float"], [data-fit="monetary"]) { text-align: end; }
381
+ .fd-lines-table td:is([data-fit="integer"], [data-fit="float"], [data-fit="monetary"]) input { text-align: end; }
382
+ /* A table reads as a table, as a grid does: a line shows its boxes and buttons where the pointer or the cursor is.
383
+ Only colours and visibility change, never a size: a line left for a click elsewhere must not move what is clicked.
384
+ A touch screen has no pointer to hover with: there the boxes always show. */
385
+ @media (hover: hover) and (pointer: fine) {
386
+ .fd-lines:not([data-cards="always"]) .fd-lines-table tbody tr:not(:hover, :focus-within) .fd-input:not([aria-invalid="true"]) { border-color: transparent; background-color: transparent; box-shadow: none; }
387
+ .fd-lines:not([data-cards="always"]) .fd-lines-table tbody tr:not(:hover, :focus-within) :is(.fd-combo-open, .fd-combo-clear) { visibility: hidden; }
388
+ }
340
389
  .fd-line-grip { display: block; margin-block-start: 7px; cursor: grab; }
390
+ /* A line dragged by its grip follows the pointer, lifted over the others, which slide out of its way. */
391
+ .fd-lines-dragging, .fd-lines-dragging * { cursor: grabbing; user-select: none; }
392
+ .fd-lines-dragging > tr:not(.fd-line-lifted) { transition: transform 0.15s ease; }
393
+ .fd-line-lifted { position: relative; z-index: 2; box-shadow: 0 6px 18px rgba(15, 20, 25, 0.16); }
394
+ .fd-line-lifted > td { background: var(--fd-surface); }
341
395
  .fd-line-delete { border: none; background: none; cursor: pointer; color: var(--fd-muted); font-size: 16px; line-height: 1; padding: 4px 6px; border-radius: 4px; min-width: 24px; min-height: 24px; }
342
396
  .fd-line-delete:hover { color: var(--fd-error); background: var(--fd-error-soft); }
343
397
  /* A table's own rules: a line's or a cell's tone and bold (Flectra's decoration-*), and buttons on a line. */
@@ -588,7 +642,8 @@ button.fd-chip-label:hover { text-decoration: underline; }
588
642
  .fd-button-primary { background: var(--fd-accent); border-color: var(--fd-accent); color: var(--fd-accent-text); }
589
643
  .fd-button-primary:hover { color: var(--fd-accent-text); filter: brightness(1.12); }
590
644
  .fd-button-danger { color: var(--fd-error); border-color: var(--fd-error); }
591
- .fd-button-danger:hover { background: var(--fd-error); color: #fff; }
645
+ /* The surface's colour on the error's: white on a light page's deep red, near-black on a dark page's coral. */
646
+ .fd-button-danger:hover { background: var(--fd-error); color: var(--fd-surface); }
592
647
  .fd-button-link { border-color: transparent; background: none; color: var(--fd-accent); padding-inline: 4px; }
593
648
  .fd-form[data-fd-skin="underline"] .fd-button { border-radius: 3px; }
594
649
  .fd-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
@@ -620,9 +675,13 @@ button.fd-chip-label:hover { text-decoration: underline; }
620
675
  .fd-sheet-layout { align-items: start; }
621
676
  /* Save and Discard closing the sheet, when the page puts them at its foot. */
622
677
  .fd-sheet-foot { margin: 4px -28px -28px; padding: 12px 28px; border-block-start: 1px solid var(--fd-border); border-end-start-radius: inherit; border-end-end-radius: inherit; }
623
- .fd-sheet-layout.fd-has-side { grid-template-columns: minmax(0, 1fr) minmax(260px, 360px); }
624
- /* The side panel goes under the sheet before the sheet is left too narrow for a label beside its value. */
625
- @container (max-width: 1000px) { .fd-sheet-layout.fd-has-side { grid-template-columns: minmax(0, 1fr); } }
678
+ /* The side panel under the sheet, the sheet taking the whole width; beside it, as Flectra's chatter, on a form of
679
+ 1534px or more — the page growing by the panel's width, so the sheet keeps its own ("none" plus a width is no
680
+ width: a full page stays full). A page that asks keeps it beside down to 600px (record-styles). */
681
+ @container (min-width: 1534px) {
682
+ .fd-sheet-layout.fd-has-side { grid-template-columns: minmax(0, 1fr) minmax(260px, 360px); max-width: calc(var(--fd-page-max, 1180px) + 376px); }
683
+ }
684
+ .fd-sheet-layout.fd-has-side[data-side-beside="always"] { grid-template-columns: minmax(0, 1fr) minmax(260px, 360px); }
626
685
  /* A part hidden at some widths of the form (hideOn): narrow up to 520px, medium up to 760px, wide above — the form's own width, as its columns. */
627
686
  .fd-form { container-name: fd-form; }
628
687
  @container fd-form (max-width: 520px) { .fd-form [data-hide-on~="narrow"] { display: none !important; } }
@@ -762,6 +821,9 @@ button.fd-chip-label:hover { text-decoration: underline; }
762
821
  .fd-property { display: grid; grid-template-columns: minmax(120px, 30%) minmax(0, 1fr); align-items: center; gap: 12px; min-width: 0; }
763
822
  .fd-property > label { color: var(--fd-muted); font-size: 13px; }
764
823
  .fd-property[data-type="boolean"] > :last-child { justify-self: start; }
824
+ /* Beside their values, as the sheet's labels are: the same label column, the same words, the same gap between halves — the properties read as fields of the sheet. */
825
+ .fd-form[data-fd-skin="underline"] .fd-property { grid-template-columns: var(--fd-label-width, 11em) minmax(0, 1fr); }
826
+ .fd-form[data-fd-skin="underline"] .fd-property > label { color: var(--fd-text); font-size: inherit; font-weight: var(--fd-label-weight); }
765
827
  @container (max-width: 520px) { .fd-property { grid-template-columns: minmax(0, 1fr); gap: 4px; } }
766
828
  .fd-progressbar {
767
829
  position: relative; height: 22px; min-width: 120px; border-radius: 999px; overflow: hidden;
@@ -948,7 +1010,9 @@ button.fd-chip-label:hover { text-decoration: underline; }
948
1010
  @media (prefers-reduced-motion: reduce) { .fd-form *, .fd-form *::before, .fd-form *::after { transition: none !important; } .fd-button[aria-busy="true"]::after { animation: none; } }
949
1011
  `;
950
1012
  /** Fieldia's whole stylesheet: the skins, then the layout over them, the inputs' details, the question kinds and the choices' details. */
951
- export const FIELDIA_CSS = SKINS_CSS + LAYOUT_CSS + INPUTS_CSS + SHEET_CSS + BUSINESS_CSS + KINDS_CSS + CHOICES_CSS + PARTS_CSS;
1013
+ // Themes' tokens after the skins' and before the page's look; their own shapes after the parts they reshape, and
1014
+ // before the page's own looks for each kind of part, which win over a theme as the page's look does.
1015
+ export const FIELDIA_CSS = SKINS_CSS + THEME_TOKENS_CSS + LAYOUT_CSS + INPUTS_CSS + SHEET_CSS + BUSINESS_CSS + THEME_RULES_CSS + KINDS_CSS + CHOICES_CSS + PARTS_CSS;
952
1016
  const STYLE_ID = 'fieldia-styles';
953
1017
  /** Add Fieldia's stylesheet to a document, once. */
954
1018
  export function installStyles(document) {
@@ -1 +1 @@
1
- {"version":3,"file":"styles.mjs","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAW,CAAC;AAEjE,+FAA+F;AAC/F,MAAM,SAAS,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAw5B3B,CAAC;AAEF,0IAA0I;AAC1I,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAEhI,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAElC,oDAAoD;AACpD,MAAM,UAAU,aAAa,CAAC,QAAkB;IAC9C,IAAI,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC;QAAE,OAAO;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC;IACpB,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IAChC,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC"}
1
+ {"version":3,"file":"styles.mjs","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAW,CAAC;AAEjE,+FAA+F;AAC/F,MAAM,SAAS,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAq9B3B,CAAC;AAEF,0IAA0I;AAC1I,iHAAiH;AACjH,qGAAqG;AACrG,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAErK,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAElC,oDAAoD;AACpD,MAAM,UAAU,aAAa,CAAC,QAAkB;IAC9C,IAAI,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC;QAAE,OAAO;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC;IACpB,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IAChC,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { Theme } from '@fieldia/core';
2
+ /**
3
+ * (Not a `styles-*.ts`: its rules are written with the selectors they share, so the script bundle's
4
+ * minifier, which takes a static stylesheet, leaves it as it is.)
5
+ *
6
+ * Themes in the style of design systems people know: the form's own tokens,
7
+ * light and dark, over the skin each is drawn on (Odoo's over `underline`,
8
+ * the rest over `outlined`), and a few rules of their own for what tokens
9
+ * cannot say — Material's filled boxes, Apple's pill buttons, Google Forms'
10
+ * question cards. They are looks in those systems' style, not their kits: a
11
+ * theme names its typeface and falls back to the system's when the app has
12
+ * not loaded it. Every colour pair a reader reads is checked against WCAG AA
13
+ * (themes.spec.ts), so a few are a shade darker than the original.
14
+ */
15
+ /** The tokens a theme sets, by their names without `--fd-`. */
16
+ export type ThemeTokens = Partial<Record<'font' | 'text' | 'muted' | 'page' | 'surface' | 'border' | 'border-strong' | 'accent' | 'accent-text' | 'accent-soft' | 'focus' | 'focus-ring' | 'error' | 'error-soft' | 'success' | 'warning' | 'info' | 'radius' | 'control-radius' | 'control-height' | 'pad-y' | 'pad-x' | 'input-border' | 'label-weight' | 'gap-x' | 'gap-y' | 'fill' | 'edge', string>>;
17
+ export declare const THEME_TOKENS: Record<Theme, {
18
+ light: ThemeTokens;
19
+ dark: ThemeTokens;
20
+ }>;
21
+ /**
22
+ * The themes' tokens: after the skins' (they win over them), before the page's
23
+ * look (whose accent, room, corners and scheme win over them). A theme's dark
24
+ * tokens are more specific than the plain dark scheme's, so they win over it.
25
+ * All in Fieldia's tokens' layer, under any rule of a host's own.
26
+ */
27
+ export declare const THEME_TOKENS_CSS: string;
28
+ /** What tokens cannot say: each theme's own shapes. After every other rule, so they win at the same weight. */
29
+ export declare const THEME_RULES_CSS: string;
@@ -0,0 +1,29 @@
1
+ import type { Theme } from '@fieldia/core';
2
+ /**
3
+ * (Not a `styles-*.ts`: its rules are written with the selectors they share, so the script bundle's
4
+ * minifier, which takes a static stylesheet, leaves it as it is.)
5
+ *
6
+ * Themes in the style of design systems people know: the form's own tokens,
7
+ * light and dark, over the skin each is drawn on (Odoo's over `underline`,
8
+ * the rest over `outlined`), and a few rules of their own for what tokens
9
+ * cannot say — Material's filled boxes, Apple's pill buttons, Google Forms'
10
+ * question cards. They are looks in those systems' style, not their kits: a
11
+ * theme names its typeface and falls back to the system's when the app has
12
+ * not loaded it. Every colour pair a reader reads is checked against WCAG AA
13
+ * (themes.spec.ts), so a few are a shade darker than the original.
14
+ */
15
+ /** The tokens a theme sets, by their names without `--fd-`. */
16
+ export type ThemeTokens = Partial<Record<'font' | 'text' | 'muted' | 'page' | 'surface' | 'border' | 'border-strong' | 'accent' | 'accent-text' | 'accent-soft' | 'focus' | 'focus-ring' | 'error' | 'error-soft' | 'success' | 'warning' | 'info' | 'radius' | 'control-radius' | 'control-height' | 'pad-y' | 'pad-x' | 'input-border' | 'label-weight' | 'gap-x' | 'gap-y' | 'fill' | 'edge', string>>;
17
+ export declare const THEME_TOKENS: Record<Theme, {
18
+ light: ThemeTokens;
19
+ dark: ThemeTokens;
20
+ }>;
21
+ /**
22
+ * The themes' tokens: after the skins' (they win over them), before the page's
23
+ * look (whose accent, room, corners and scheme win over them). A theme's dark
24
+ * tokens are more specific than the plain dark scheme's, so they win over it.
25
+ * All in Fieldia's tokens' layer, under any rule of a host's own.
26
+ */
27
+ export declare const THEME_TOKENS_CSS: string;
28
+ /** What tokens cannot say: each theme's own shapes. After every other rule, so they win at the same weight. */
29
+ export declare const THEME_RULES_CSS: string;