@fieldia/designer 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/package.json +4 -4
  2. package/src/lib/chrome.js +11 -0
  3. package/src/lib/chrome.js.map +1 -1
  4. package/src/lib/chrome.mjs +11 -0
  5. package/src/lib/chrome.mjs.map +1 -1
  6. package/src/lib/date-setting.d.mts +49 -0
  7. package/src/lib/date-setting.d.ts +49 -0
  8. package/src/lib/date-setting.js +125 -0
  9. package/src/lib/date-setting.js.map +1 -0
  10. package/src/lib/date-setting.mjs +122 -0
  11. package/src/lib/date-setting.mjs.map +1 -0
  12. package/src/lib/designer.d.mts +10 -1
  13. package/src/lib/designer.d.ts +10 -1
  14. package/src/lib/designer.js +13 -2
  15. package/src/lib/designer.js.map +1 -1
  16. package/src/lib/designer.mjs +13 -2
  17. package/src/lib/designer.mjs.map +1 -1
  18. package/src/lib/head-commands.d.mts +11 -1
  19. package/src/lib/head-commands.d.ts +11 -1
  20. package/src/lib/head-commands.js +33 -1
  21. package/src/lib/head-commands.js.map +1 -1
  22. package/src/lib/head-commands.mjs +30 -1
  23. package/src/lib/head-commands.mjs.map +1 -1
  24. package/src/lib/head-properties.js +19 -6
  25. package/src/lib/head-properties.js.map +1 -1
  26. package/src/lib/head-properties.mjs +19 -6
  27. package/src/lib/head-properties.mjs.map +1 -1
  28. package/src/lib/inline-settings.js +16 -10
  29. package/src/lib/inline-settings.js.map +1 -1
  30. package/src/lib/inline-settings.mjs +16 -10
  31. package/src/lib/inline-settings.mjs.map +1 -1
  32. package/src/lib/input-commands.js +3 -2
  33. package/src/lib/input-commands.js.map +1 -1
  34. package/src/lib/input-commands.mjs +3 -2
  35. package/src/lib/input-commands.mjs.map +1 -1
  36. package/src/lib/kind-settings-choices.js +16 -7
  37. package/src/lib/kind-settings-choices.js.map +1 -1
  38. package/src/lib/kind-settings-choices.mjs +16 -7
  39. package/src/lib/kind-settings-choices.mjs.map +1 -1
  40. package/src/lib/kind-settings-inputs.js +116 -58
  41. package/src/lib/kind-settings-inputs.js.map +1 -1
  42. package/src/lib/kind-settings-inputs.mjs +116 -58
  43. package/src/lib/kind-settings-inputs.mjs.map +1 -1
  44. package/src/lib/kind-settings-picker.js +16 -9
  45. package/src/lib/kind-settings-picker.js.map +1 -1
  46. package/src/lib/kind-settings-picker.mjs +16 -9
  47. package/src/lib/kind-settings-picker.mjs.map +1 -1
  48. package/src/lib/kind-settings-structures.js +28 -14
  49. package/src/lib/kind-settings-structures.js.map +1 -1
  50. package/src/lib/kind-settings-structures.mjs +29 -15
  51. package/src/lib/kind-settings-structures.mjs.map +1 -1
  52. package/src/lib/kind-settings.js +47 -43
  53. package/src/lib/kind-settings.js.map +1 -1
  54. package/src/lib/kind-settings.mjs +47 -43
  55. package/src/lib/kind-settings.mjs.map +1 -1
  56. package/src/lib/list-properties.js +100 -55
  57. package/src/lib/list-properties.js.map +1 -1
  58. package/src/lib/list-properties.mjs +100 -55
  59. package/src/lib/list-properties.mjs.map +1 -1
  60. package/src/lib/locales/ar/index.js +2 -1
  61. package/src/lib/locales/ar/index.js.map +1 -1
  62. package/src/lib/locales/ar/index.mjs +2 -1
  63. package/src/lib/locales/ar/index.mjs.map +1 -1
  64. package/src/lib/locales/ar/inputs.d.mts +2 -0
  65. package/src/lib/locales/ar/inputs.d.ts +2 -0
  66. package/src/lib/locales/ar/inputs.js +20 -0
  67. package/src/lib/locales/ar/inputs.js.map +1 -0
  68. package/src/lib/locales/ar/inputs.mjs +17 -0
  69. package/src/lib/locales/ar/inputs.mjs.map +1 -0
  70. package/src/lib/locales/en/index.d.mts +15 -0
  71. package/src/lib/locales/en/index.d.ts +15 -0
  72. package/src/lib/locales/en/index.js +2 -1
  73. package/src/lib/locales/en/index.js.map +1 -1
  74. package/src/lib/locales/en/index.mjs +2 -1
  75. package/src/lib/locales/en/index.mjs.map +1 -1
  76. package/src/lib/locales/en/inputs.d.mts +26 -0
  77. package/src/lib/locales/en/inputs.d.ts +26 -0
  78. package/src/lib/locales/en/inputs.js +30 -0
  79. package/src/lib/locales/en/inputs.js.map +1 -0
  80. package/src/lib/locales/en/inputs.mjs +27 -0
  81. package/src/lib/locales/en/inputs.mjs.map +1 -0
  82. package/src/lib/number-box.d.mts +66 -0
  83. package/src/lib/number-box.d.ts +66 -0
  84. package/src/lib/number-box.js +153 -0
  85. package/src/lib/number-box.js.map +1 -0
  86. package/src/lib/number-box.mjs +149 -0
  87. package/src/lib/number-box.mjs.map +1 -0
  88. package/src/lib/page-json.d.mts +3 -1
  89. package/src/lib/page-json.d.ts +3 -1
  90. package/src/lib/page-json.js +5 -3
  91. package/src/lib/page-json.js.map +1 -1
  92. package/src/lib/page-json.mjs +5 -3
  93. package/src/lib/page-json.mjs.map +1 -1
  94. package/src/lib/panel-block.js +16 -5
  95. package/src/lib/panel-block.js.map +1 -1
  96. package/src/lib/panel-block.mjs +16 -5
  97. package/src/lib/panel-block.mjs.map +1 -1
  98. package/src/lib/panel-layout.js +20 -15
  99. package/src/lib/panel-layout.js.map +1 -1
  100. package/src/lib/panel-layout.mjs +20 -15
  101. package/src/lib/panel-layout.mjs.map +1 -1
  102. package/src/lib/panel-look.js +21 -14
  103. package/src/lib/panel-look.js.map +1 -1
  104. package/src/lib/panel-look.mjs +21 -14
  105. package/src/lib/panel-look.mjs.map +1 -1
  106. package/src/lib/panel-map.js +53 -20
  107. package/src/lib/panel-map.js.map +1 -1
  108. package/src/lib/panel-map.mjs +53 -20
  109. package/src/lib/panel-map.mjs.map +1 -1
  110. package/src/lib/rules-answers.d.mts +1 -1
  111. package/src/lib/rules-answers.d.ts +1 -1
  112. package/src/lib/rules-answers.js +45 -21
  113. package/src/lib/rules-answers.js.map +1 -1
  114. package/src/lib/rules-answers.mjs +45 -21
  115. package/src/lib/rules-answers.mjs.map +1 -1
  116. package/src/lib/rules-formula-box.d.mts +7 -3
  117. package/src/lib/rules-formula-box.d.ts +7 -3
  118. package/src/lib/rules-formula-box.js +26 -6
  119. package/src/lib/rules-formula-box.js.map +1 -1
  120. package/src/lib/rules-formula-box.mjs +26 -6
  121. package/src/lib/rules-formula-box.mjs.map +1 -1
  122. package/src/lib/rules-formula.js +7 -5
  123. package/src/lib/rules-formula.js.map +1 -1
  124. package/src/lib/rules-formula.mjs +8 -6
  125. package/src/lib/rules-formula.mjs.map +1 -1
  126. package/src/lib/rules-worked-out.js +66 -12
  127. package/src/lib/rules-worked-out.js.map +1 -1
  128. package/src/lib/rules-worked-out.mjs +66 -12
  129. package/src/lib/rules-worked-out.mjs.map +1 -1
  130. package/src/lib/setting-refusals.d.mts +3 -0
  131. package/src/lib/setting-refusals.d.ts +3 -0
  132. package/src/lib/setting-refusals.js +25 -0
  133. package/src/lib/setting-refusals.js.map +1 -0
  134. package/src/lib/setting-refusals.mjs +22 -0
  135. package/src/lib/setting-refusals.mjs.map +1 -0
  136. package/src/lib/table-panel.js +16 -5
  137. package/src/lib/table-panel.js.map +1 -1
  138. package/src/lib/table-panel.mjs +16 -5
  139. package/src/lib/table-panel.mjs.map +1 -1
  140. package/src/lib/work-text.d.mts +10 -2
  141. package/src/lib/work-text.d.ts +10 -2
  142. package/src/lib/work-text.js +12 -23
  143. package/src/lib/work-text.js.map +1 -1
  144. package/src/lib/work-text.mjs +12 -21
  145. package/src/lib/work-text.mjs.map +1 -1
@@ -0,0 +1,27 @@
1
+ /**
2
+ * What the designer says of a setting typed into one of its own boxes that it
3
+ * cannot take — out of range, not a number, half-typed — and of a formula that
4
+ * does not read yet: the setting keeps what it held, and the box says why.
5
+ * `setting` is the setting's own name ("Height"); numbers come as written.
6
+ */
7
+ export const inputs = {
8
+ settingRange: (setting, min, max) => `${setting} is a whole number from ${min} to ${max}`,
9
+ settingNumberRange: (setting, min, max) => `${setting} is a number from ${min} to ${max}`,
10
+ settingAtLeast: (setting, min) => `${setting} is a whole number, ${min} or more`,
11
+ settingMoreThan: (setting, min) => `${setting} is more than ${min}`,
12
+ settingFewer: (setting, n) => `${setting} is fewer than the ${n} options`,
13
+ settingNeedsNumber: (setting) => `${setting} needs a number`,
14
+ /** A date the designer did not take, for a reason none of the above names. */
15
+ settingDateRefused: (setting) => `${setting} cannot be that date on this page`,
16
+ /** After any of the above: what the page keeps meanwhile. */
17
+ settingStays: (value) => `It stays ${value}.`,
18
+ /** A setting brought into its range, and said so. */
19
+ settingSetTo: (setting, min, max, value) => `${setting} runs from ${min} to ${max}, so it is ${value}`,
20
+ /** A formula that does not read yet (`problem`): the one the page keeps, or none. */
21
+ formulaKept: (problem, formula) => `Not in force yet: ${problem}. The page keeps ${formula}.`,
22
+ formulaNone: (problem) => `Not in force yet: ${problem}. The page has no formula until this one reads.`,
23
+ formulaPoint: 'In a formula the decimal mark is a point or ٫, like 1.5',
24
+ /** A grid's column width (`track`) out of range, in pixels. */
25
+ trackRange: (track, min, max) => `“${track}”: a column is ${min} to ${max} px wide`,
26
+ };
27
+ //# sourceMappingURL=inputs.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputs.mjs","sourceRoot":"","sources":["../../../../../../../libs/designer/src/lib/locales/en/inputs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,YAAY,EAAE,CAAC,OAAe,EAAE,GAAoB,EAAE,GAAoB,EAAE,EAAE,CAAC,GAAG,OAAO,2BAA2B,GAAG,OAAO,GAAG,EAAE;IACnI,kBAAkB,EAAE,CAAC,OAAe,EAAE,GAAoB,EAAE,GAAoB,EAAE,EAAE,CAAC,GAAG,OAAO,qBAAqB,GAAG,OAAO,GAAG,EAAE;IACnI,cAAc,EAAE,CAAC,OAAe,EAAE,GAAoB,EAAE,EAAE,CAAC,GAAG,OAAO,uBAAuB,GAAG,UAAU;IACzG,eAAe,EAAE,CAAC,OAAe,EAAE,GAAoB,EAAE,EAAE,CAAC,GAAG,OAAO,iBAAiB,GAAG,EAAE;IAC5F,YAAY,EAAE,CAAC,OAAe,EAAE,CAAS,EAAE,EAAE,CAAC,GAAG,OAAO,sBAAsB,CAAC,UAAU;IACzF,kBAAkB,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,OAAO,iBAAiB;IACpE,8EAA8E;IAC9E,kBAAkB,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,OAAO,mCAAmC;IACtF,6DAA6D;IAC7D,YAAY,EAAE,CAAC,KAAsB,EAAE,EAAE,CAAC,YAAY,KAAK,GAAG;IAC9D,qDAAqD;IACrD,YAAY,EAAE,CAAC,OAAe,EAAE,GAAoB,EAAE,GAAoB,EAAE,KAAsB,EAAE,EAAE,CAAC,GAAG,OAAO,cAAc,GAAG,OAAO,GAAG,cAAc,KAAK,EAAE;IACjK,qFAAqF;IACrF,WAAW,EAAE,CAAC,OAAe,EAAE,OAAe,EAAE,EAAE,CAAC,qBAAqB,OAAO,oBAAoB,OAAO,GAAG;IAC7G,WAAW,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,qBAAqB,OAAO,iDAAiD;IAC/G,YAAY,EAAE,yDAAyD;IACvE,+DAA+D;IAC/D,UAAU,EAAE,CAAC,KAAa,EAAE,GAAoB,EAAE,GAAoB,EAAE,EAAE,CAAC,IAAI,KAAK,kBAAkB,GAAG,OAAO,GAAG,UAAU;CAC9H,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { type Locale } from '@fieldia/core';
2
+ import type { ElementFactory } from './chrome.mjs';
3
+ import type { DesignerLocale, DesignerWords } from './designer-words.mjs';
4
+ /**
5
+ * The designer's number box: every number setting — a field's limits, a
6
+ * height, a label width, rows on a page, a map's minutes — is typed into one
7
+ * of these, never the browser's own number box, which follows the browser's
8
+ * language, drops Arabic digits and empties itself on what it cannot read.
9
+ *
10
+ * It is the form's number box (FIELDIA INPUT RULES): Arabic-Indic and Persian
11
+ * digits, ٫ and a decimal comma read; letters, a misplaced minus, a decimal
12
+ * mark in a whole number are refused as they are typed, said under the box.
13
+ * What is typed is kept as the box is left — while typing, only a live
14
+ * preview's text that reads and fits. Out of range, half-typed or unreadable,
15
+ * the setting keeps what it had, the box shows it again, and the words under
16
+ * it say what fits: "Height is a whole number, 120 or more. It stays 600."
17
+ * Emptied, an optional limit goes; a setting that must have a number comes
18
+ * back, said. A number the designer refuses because of another setting is
19
+ * said at the box too, in the designer's words ("From is not less than To"),
20
+ * never only in the issues far above it. Keys typed after a refused one are
21
+ * held with it (the form's rules), and left so, the setting stays as it was,
22
+ * said. ↑ and ↓ step it, as the browser's box did.
23
+ */
24
+ export interface SettingNumberOptions {
25
+ /** The setting's own name in the words said of it ("Height"), and its box's name unless `attrs` names it. */
26
+ label: string;
27
+ /** The box's class, its name for a screen reader, its placeholder. */
28
+ attrs?: Record<string, string>;
29
+ /** Whole numbers only. */
30
+ integer?: boolean;
31
+ /** The least it takes, included, and the most. */
32
+ min?: number;
33
+ max?: number;
34
+ /** The least it takes, not included: "Most is more than 0". */
35
+ above?: number;
36
+ /** What ↑ and ↓ add and take away; 1 unless said. */
37
+ step?: number;
38
+ /** Emptied, the setting goes (an optional limit); else what is saved comes back, said. */
39
+ optional?: boolean;
40
+ /** Kept as it is typed too, once what is typed reads and fits: a preview that follows the keys. */
41
+ live?: boolean;
42
+ /** More than a range: why a value that fits it does not fit the setting ("fewer than the 3 options"), or null. */
43
+ check?(value: number): string | null;
44
+ /** What the setting holds now: shown once the box is left. */
45
+ saved(): number | null | undefined;
46
+ /** Keep a number, or take the setting away (null); false when the designer refused it. */
47
+ commit(value: number | null): boolean | void;
48
+ }
49
+ export interface SettingNumber {
50
+ input: HTMLInputElement;
51
+ /** Show what is saved, unless the box is being typed in. */
52
+ refresh(): void;
53
+ destroy(): void;
54
+ }
55
+ /** What a designer box needs of its designer: its words, its language, and why it last refused an edit. */
56
+ export interface NumberBoxHost {
57
+ readonly words: DesignerWords;
58
+ readonly locale: DesignerLocale | null;
59
+ /** The designer's state: `issues`, why the last edit was refused ("From is not less than To"). */
60
+ getState?(): {
61
+ readonly issues: readonly string[];
62
+ };
63
+ }
64
+ /** A number as a setting's box writes it: plain, in Latin digits, all its places, never in exponent form. */
65
+ export declare function plainNumber(value: number, locale?: Locale): string;
66
+ export declare function settingNumber(el: ElementFactory, host: NumberBoxHost, options: SettingNumberOptions): SettingNumber;
@@ -0,0 +1,66 @@
1
+ import { type Locale } from '@fieldia/core';
2
+ import type { ElementFactory } from './chrome';
3
+ import type { DesignerLocale, DesignerWords } from './designer-words';
4
+ /**
5
+ * The designer's number box: every number setting — a field's limits, a
6
+ * height, a label width, rows on a page, a map's minutes — is typed into one
7
+ * of these, never the browser's own number box, which follows the browser's
8
+ * language, drops Arabic digits and empties itself on what it cannot read.
9
+ *
10
+ * It is the form's number box (FIELDIA INPUT RULES): Arabic-Indic and Persian
11
+ * digits, ٫ and a decimal comma read; letters, a misplaced minus, a decimal
12
+ * mark in a whole number are refused as they are typed, said under the box.
13
+ * What is typed is kept as the box is left — while typing, only a live
14
+ * preview's text that reads and fits. Out of range, half-typed or unreadable,
15
+ * the setting keeps what it had, the box shows it again, and the words under
16
+ * it say what fits: "Height is a whole number, 120 or more. It stays 600."
17
+ * Emptied, an optional limit goes; a setting that must have a number comes
18
+ * back, said. A number the designer refuses because of another setting is
19
+ * said at the box too, in the designer's words ("From is not less than To"),
20
+ * never only in the issues far above it. Keys typed after a refused one are
21
+ * held with it (the form's rules), and left so, the setting stays as it was,
22
+ * said. ↑ and ↓ step it, as the browser's box did.
23
+ */
24
+ export interface SettingNumberOptions {
25
+ /** The setting's own name in the words said of it ("Height"), and its box's name unless `attrs` names it. */
26
+ label: string;
27
+ /** The box's class, its name for a screen reader, its placeholder. */
28
+ attrs?: Record<string, string>;
29
+ /** Whole numbers only. */
30
+ integer?: boolean;
31
+ /** The least it takes, included, and the most. */
32
+ min?: number;
33
+ max?: number;
34
+ /** The least it takes, not included: "Most is more than 0". */
35
+ above?: number;
36
+ /** What ↑ and ↓ add and take away; 1 unless said. */
37
+ step?: number;
38
+ /** Emptied, the setting goes (an optional limit); else what is saved comes back, said. */
39
+ optional?: boolean;
40
+ /** Kept as it is typed too, once what is typed reads and fits: a preview that follows the keys. */
41
+ live?: boolean;
42
+ /** More than a range: why a value that fits it does not fit the setting ("fewer than the 3 options"), or null. */
43
+ check?(value: number): string | null;
44
+ /** What the setting holds now: shown once the box is left. */
45
+ saved(): number | null | undefined;
46
+ /** Keep a number, or take the setting away (null); false when the designer refused it. */
47
+ commit(value: number | null): boolean | void;
48
+ }
49
+ export interface SettingNumber {
50
+ input: HTMLInputElement;
51
+ /** Show what is saved, unless the box is being typed in. */
52
+ refresh(): void;
53
+ destroy(): void;
54
+ }
55
+ /** What a designer box needs of its designer: its words, its language, and why it last refused an edit. */
56
+ export interface NumberBoxHost {
57
+ readonly words: DesignerWords;
58
+ readonly locale: DesignerLocale | null;
59
+ /** The designer's state: `issues`, why the last edit was refused ("From is not less than To"). */
60
+ getState?(): {
61
+ readonly issues: readonly string[];
62
+ };
63
+ }
64
+ /** A number as a setting's box writes it: plain, in Latin digits, all its places, never in exponent form. */
65
+ export declare function plainNumber(value: number, locale?: Locale): string;
66
+ export declare function settingNumber(el: ElementFactory, host: NumberBoxHost, options: SettingNumberOptions): SettingNumber;
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.plainNumber = plainNumber;
4
+ exports.settingNumber = settingNumber;
5
+ const core_1 = require("@fieldia/core");
6
+ const widgets_1 = require("@fieldia/widgets");
7
+ /** A number as a setting's box writes it: plain, in Latin digits, all its places, never in exponent form. */
8
+ function plainNumber(value, locale = 'en') {
9
+ return (0, widgets_1.formatPlain)(value, Math.min((0, core_1.placesOf)(value), 20), locale);
10
+ }
11
+ function settingNumber(el, host, options) {
12
+ const locale = host.locale ?? 'en';
13
+ const w = host.words.inputs;
14
+ // Read as they are now each time: a box may change its name, or whether it takes whole numbers, with its field.
15
+ const least = () => options.min ?? options.above;
16
+ const limits = () => ({ integer: !!options.integer, ...(least() !== undefined ? { min: least() } : {}) });
17
+ const input = el('input', { type: 'text', class: 'fd-input', autocomplete: 'off', 'aria-label': options.label, inputmode: (0, widgets_1.numberKeyboard)(limits()), ...options.attrs });
18
+ const hint = (0, widgets_1.refusalHint)(input);
19
+ const box = {
20
+ get label() {
21
+ return options.label;
22
+ },
23
+ locale,
24
+ labels: widgets_1.WIDGET_LABELS[locale] ?? widgets_1.WIDGET_LABELS.en,
25
+ messages: core_1.MESSAGES[locale] ?? core_1.MESSAGES.en,
26
+ limits,
27
+ };
28
+ const checks = (0, widgets_1.guard)(input, (0, widgets_1.numberRules)(box), hint);
29
+ const focused = () => input.ownerDocument.activeElement === input;
30
+ const shown = (value) => (typeof value === 'number' && Number.isFinite(value) ? plainNumber(value, locale) : '');
31
+ const said = (value) => plainNumber(value, locale);
32
+ /** What fits, in words: its range, or that it needs a number. */
33
+ const fits = () => {
34
+ const { label, integer, min, max, above } = options;
35
+ if (above !== undefined)
36
+ return w.settingMoreThan(label, said(above));
37
+ if (min !== undefined && max !== undefined)
38
+ return integer ? w.settingRange(label, said(min), said(max)) : w.settingNumberRange(label, said(min), said(max));
39
+ if (min !== undefined && integer)
40
+ return w.settingAtLeast(label, said(min));
41
+ if (integer)
42
+ return (0, core_1.fill)((core_1.MESSAGES[locale] ?? core_1.MESSAGES.en).integer, { label });
43
+ return w.settingNeedsNumber(label);
44
+ };
45
+ /** Why a number read does not fit, or null. */
46
+ const misfit = (value) => {
47
+ const { integer, min, max, above } = options;
48
+ if ((integer && !Number.isInteger(value)) || (min !== undefined && value < min) || (max !== undefined && value > max) || (above !== undefined && value <= above))
49
+ return fits();
50
+ return options.check?.(value) ?? null;
51
+ };
52
+ /**
53
+ * The text the box was last left with, and what was said of it: a browser says change and then blur as a box is
54
+ * left, and Enter says change too; the second is the same leaving, and says again what the first said (a blur
55
+ * takes the hint away).
56
+ */
57
+ let left = null;
58
+ /** What the setting held as the box was entered: a live preview's keys, which kept what read on the way, go back to it. */
59
+ let entered;
60
+ input.addEventListener('focus', () => {
61
+ entered = options.saved();
62
+ left = null;
63
+ });
64
+ /** The box back to what was saved before it was typed in, and why, said under it. */
65
+ const keep = (why) => {
66
+ let saved = options.saved();
67
+ // "600" passed by 60 on its way: the preview's 60 was never what was meant.
68
+ if (options.live && entered !== undefined && saved !== entered && options.commit(entered ?? null) !== false)
69
+ saved = entered;
70
+ input.value = shown(saved);
71
+ checks.accept();
72
+ const words = typeof saved === 'number' ? `${why.replace(/[.。]$/, '')}. ${w.settingStays(said(saved))}` : why;
73
+ hint.show(words);
74
+ left = { text: input.value, said: words };
75
+ };
76
+ /** A number (or none) kept, and shown as the box writes it; refused by the designer, what is saved comes back, with why under the box. */
77
+ const kept = (value) => {
78
+ const done = value === (options.saved() ?? null) || options.commit(value) !== false;
79
+ if (!done)
80
+ return keep(host.getState?.().issues[0] ?? fits());
81
+ input.value = shown(value);
82
+ checks.accept();
83
+ left = { text: input.value, said: null };
84
+ };
85
+ /** The box left: what it holds kept when it reads and fits, else the setting as it was, and why. */
86
+ function leave() {
87
+ if (left && left.text === input.value) {
88
+ if (left.said)
89
+ hint.show(left.said);
90
+ return;
91
+ }
92
+ // Keys held after a refused one ("2٫5" in a whole number, where the box shows "2"): what was typed does not fit.
93
+ if (checks.held())
94
+ return keep(fits());
95
+ const read = (0, core_1.readNumber)(input.value, locale);
96
+ if (read.ok && read.value === null)
97
+ return options.optional ? kept(null) : keep(w.settingNeedsNumber(options.label));
98
+ if (!read.ok || read.value === null)
99
+ return keep(fits());
100
+ const wrong = misfit(read.value);
101
+ if (wrong)
102
+ return keep(wrong);
103
+ kept(read.value);
104
+ }
105
+ input.addEventListener('input', () => {
106
+ left = null;
107
+ if (!options.live)
108
+ return;
109
+ const read = (0, core_1.readNumber)(input.value, locale);
110
+ if (read.ok && read.value !== null && read.value !== options.saved() && !misfit(read.value))
111
+ options.commit(read.value);
112
+ });
113
+ // Left by Tab or a click elsewhere, or Enter pressed: what is typed is taken, or said not to fit.
114
+ input.addEventListener('change', leave);
115
+ input.addEventListener('blur', leave);
116
+ input.addEventListener('keydown', (event) => {
117
+ if (event.isComposing || event.altKey || event.ctrlKey || event.metaKey)
118
+ return;
119
+ if (event.key === 'Enter')
120
+ return leave();
121
+ if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown')
122
+ return;
123
+ // ↑ and ↓ step the number, as the browser's box did; at the end of its range, they say the range.
124
+ const read = (0, core_1.readNumber)(input.value, locale);
125
+ const from = read.ok ? (read.value ?? options.saved() ?? least() ?? 0) : null;
126
+ if (from === null)
127
+ return;
128
+ event.preventDefault();
129
+ const step = options.step ?? 1;
130
+ const next = Math.round((from + (event.key === 'ArrowUp' ? step : -step)) * 1e9) / 1e9;
131
+ if (misfit(next))
132
+ return hint.show(fits());
133
+ input.value = shown(next);
134
+ checks.accept();
135
+ hint.hide();
136
+ input.dispatchEvent(new Event('input', { bubbles: true }));
137
+ });
138
+ return {
139
+ input,
140
+ refresh: () => {
141
+ input.inputMode = (0, widgets_1.numberKeyboard)(limits());
142
+ if (focused())
143
+ return;
144
+ const text = shown(options.saved());
145
+ if (input.value !== text) {
146
+ input.value = text;
147
+ checks.accept();
148
+ }
149
+ },
150
+ destroy: () => checks.destroy(),
151
+ };
152
+ }
153
+ //# sourceMappingURL=number-box.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-box.js","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/number-box.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ import { fill, MESSAGES, placesOf, readNumber } from '@fieldia/core';
2
+ import { formatPlain, guard, numberKeyboard, numberRules, refusalHint, WIDGET_LABELS } from '@fieldia/widgets';
3
+ /** A number as a setting's box writes it: plain, in Latin digits, all its places, never in exponent form. */
4
+ export function plainNumber(value, locale = 'en') {
5
+ return formatPlain(value, Math.min(placesOf(value), 20), locale);
6
+ }
7
+ export function settingNumber(el, host, options) {
8
+ const locale = host.locale ?? 'en';
9
+ const w = host.words.inputs;
10
+ // Read as they are now each time: a box may change its name, or whether it takes whole numbers, with its field.
11
+ const least = () => options.min ?? options.above;
12
+ const limits = () => ({ integer: !!options.integer, ...(least() !== undefined ? { min: least() } : {}) });
13
+ const input = el('input', { type: 'text', class: 'fd-input', autocomplete: 'off', 'aria-label': options.label, inputmode: numberKeyboard(limits()), ...options.attrs });
14
+ const hint = refusalHint(input);
15
+ const box = {
16
+ get label() {
17
+ return options.label;
18
+ },
19
+ locale,
20
+ labels: WIDGET_LABELS[locale] ?? WIDGET_LABELS.en,
21
+ messages: MESSAGES[locale] ?? MESSAGES.en,
22
+ limits,
23
+ };
24
+ const checks = guard(input, numberRules(box), hint);
25
+ const focused = () => input.ownerDocument.activeElement === input;
26
+ const shown = (value) => (typeof value === 'number' && Number.isFinite(value) ? plainNumber(value, locale) : '');
27
+ const said = (value) => plainNumber(value, locale);
28
+ /** What fits, in words: its range, or that it needs a number. */
29
+ const fits = () => {
30
+ const { label, integer, min, max, above } = options;
31
+ if (above !== undefined)
32
+ return w.settingMoreThan(label, said(above));
33
+ if (min !== undefined && max !== undefined)
34
+ return integer ? w.settingRange(label, said(min), said(max)) : w.settingNumberRange(label, said(min), said(max));
35
+ if (min !== undefined && integer)
36
+ return w.settingAtLeast(label, said(min));
37
+ if (integer)
38
+ return fill((MESSAGES[locale] ?? MESSAGES.en).integer, { label });
39
+ return w.settingNeedsNumber(label);
40
+ };
41
+ /** Why a number read does not fit, or null. */
42
+ const misfit = (value) => {
43
+ const { integer, min, max, above } = options;
44
+ if ((integer && !Number.isInteger(value)) || (min !== undefined && value < min) || (max !== undefined && value > max) || (above !== undefined && value <= above))
45
+ return fits();
46
+ return options.check?.(value) ?? null;
47
+ };
48
+ /**
49
+ * The text the box was last left with, and what was said of it: a browser says change and then blur as a box is
50
+ * left, and Enter says change too; the second is the same leaving, and says again what the first said (a blur
51
+ * takes the hint away).
52
+ */
53
+ let left = null;
54
+ /** What the setting held as the box was entered: a live preview's keys, which kept what read on the way, go back to it. */
55
+ let entered;
56
+ input.addEventListener('focus', () => {
57
+ entered = options.saved();
58
+ left = null;
59
+ });
60
+ /** The box back to what was saved before it was typed in, and why, said under it. */
61
+ const keep = (why) => {
62
+ let saved = options.saved();
63
+ // "600" passed by 60 on its way: the preview's 60 was never what was meant.
64
+ if (options.live && entered !== undefined && saved !== entered && options.commit(entered ?? null) !== false)
65
+ saved = entered;
66
+ input.value = shown(saved);
67
+ checks.accept();
68
+ const words = typeof saved === 'number' ? `${why.replace(/[.。]$/, '')}. ${w.settingStays(said(saved))}` : why;
69
+ hint.show(words);
70
+ left = { text: input.value, said: words };
71
+ };
72
+ /** A number (or none) kept, and shown as the box writes it; refused by the designer, what is saved comes back, with why under the box. */
73
+ const kept = (value) => {
74
+ const done = value === (options.saved() ?? null) || options.commit(value) !== false;
75
+ if (!done)
76
+ return keep(host.getState?.().issues[0] ?? fits());
77
+ input.value = shown(value);
78
+ checks.accept();
79
+ left = { text: input.value, said: null };
80
+ };
81
+ /** The box left: what it holds kept when it reads and fits, else the setting as it was, and why. */
82
+ function leave() {
83
+ if (left && left.text === input.value) {
84
+ if (left.said)
85
+ hint.show(left.said);
86
+ return;
87
+ }
88
+ // Keys held after a refused one ("2٫5" in a whole number, where the box shows "2"): what was typed does not fit.
89
+ if (checks.held())
90
+ return keep(fits());
91
+ const read = readNumber(input.value, locale);
92
+ if (read.ok && read.value === null)
93
+ return options.optional ? kept(null) : keep(w.settingNeedsNumber(options.label));
94
+ if (!read.ok || read.value === null)
95
+ return keep(fits());
96
+ const wrong = misfit(read.value);
97
+ if (wrong)
98
+ return keep(wrong);
99
+ kept(read.value);
100
+ }
101
+ input.addEventListener('input', () => {
102
+ left = null;
103
+ if (!options.live)
104
+ return;
105
+ const read = readNumber(input.value, locale);
106
+ if (read.ok && read.value !== null && read.value !== options.saved() && !misfit(read.value))
107
+ options.commit(read.value);
108
+ });
109
+ // Left by Tab or a click elsewhere, or Enter pressed: what is typed is taken, or said not to fit.
110
+ input.addEventListener('change', leave);
111
+ input.addEventListener('blur', leave);
112
+ input.addEventListener('keydown', (event) => {
113
+ if (event.isComposing || event.altKey || event.ctrlKey || event.metaKey)
114
+ return;
115
+ if (event.key === 'Enter')
116
+ return leave();
117
+ if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown')
118
+ return;
119
+ // ↑ and ↓ step the number, as the browser's box did; at the end of its range, they say the range.
120
+ const read = readNumber(input.value, locale);
121
+ const from = read.ok ? (read.value ?? options.saved() ?? least() ?? 0) : null;
122
+ if (from === null)
123
+ return;
124
+ event.preventDefault();
125
+ const step = options.step ?? 1;
126
+ const next = Math.round((from + (event.key === 'ArrowUp' ? step : -step)) * 1e9) / 1e9;
127
+ if (misfit(next))
128
+ return hint.show(fits());
129
+ input.value = shown(next);
130
+ checks.accept();
131
+ hint.hide();
132
+ input.dispatchEvent(new Event('input', { bubbles: true }));
133
+ });
134
+ return {
135
+ input,
136
+ refresh: () => {
137
+ input.inputMode = numberKeyboard(limits());
138
+ if (focused())
139
+ return;
140
+ const text = shown(options.saved());
141
+ if (input.value !== text) {
142
+ input.value = text;
143
+ checks.accept();
144
+ }
145
+ },
146
+ destroy: () => checks.destroy(),
147
+ };
148
+ }
149
+ //# sourceMappingURL=number-box.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-box.mjs","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/number-box.ts"],"names":[],"mappings":"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"}
@@ -38,5 +38,7 @@ export interface PageJsonCommands {
38
38
  export interface PageJsonDeps {
39
39
  getPage(): Page;
40
40
  apply(edit: (draft: Page) => void): boolean;
41
+ /** The designer's words, for the problems it says. */
42
+ words?: DesignerWords;
41
43
  }
42
- export declare function pageJsonCommands({ getPage, apply }: PageJsonDeps): PageJsonCommands;
44
+ export declare function pageJsonCommands({ getPage, apply, words }: PageJsonDeps): PageJsonCommands;
@@ -38,5 +38,7 @@ export interface PageJsonCommands {
38
38
  export interface PageJsonDeps {
39
39
  getPage(): Page;
40
40
  apply(edit: (draft: Page) => void): boolean;
41
+ /** The designer's words, for the problems it says. */
42
+ words?: DesignerWords;
41
43
  }
42
- export declare function pageJsonCommands({ getPage, apply }: PageJsonDeps): PageJsonCommands;
44
+ export declare function pageJsonCommands({ getPage, apply, words }: PageJsonDeps): PageJsonCommands;
@@ -6,6 +6,7 @@ exports.pageJsonCommands = pageJsonCommands;
6
6
  const core_1 = require("@fieldia/core");
7
7
  const json_text_1 = require("./json-text");
8
8
  const en_1 = require("./locales/en");
9
+ const setting_refusals_1 = require("./setting-refusals");
9
10
  /** The page as JSON: two spaces deep, its keys in the order the page keeps them. */
10
11
  function pageToJson(page) {
11
12
  return JSON.stringify(page, null, 2);
@@ -18,16 +19,17 @@ function readPage(text, words = en_1.en) {
18
19
  const checked = (0, core_1.validatePage)(read.value);
19
20
  if (checked.ok)
20
21
  return { value: read.value, tree: read.tree, page: checked.page, problems: [] };
21
- const problems = checked.issues.map((issue) => ({ ...(0, json_text_1.placeOf)(text, read.tree, issue.path), path: issue.path, message: issue.message }));
22
+ // A number setting's problem in its own words: "Minutes is a whole number from 1 to 120", not the format's English.
23
+ const problems = checked.issues.map((issue) => ({ ...(0, json_text_1.placeOf)(text, read.tree, issue.path), path: issue.path, message: (0, setting_refusals_1.settingRefusal)(issue.path, words) ?? issue.message }));
22
24
  // In reading order, as the person meets them going down the text.
23
25
  problems.sort((a, b) => a.line - b.line || a.column - b.column);
24
26
  return { value: read.value, tree: read.tree, page: null, problems };
25
27
  }
26
- function pageJsonCommands({ getPage, apply }) {
28
+ function pageJsonCommands({ getPage, apply, words = en_1.en }) {
27
29
  return {
28
30
  pageJson: () => pageToJson(getPage()),
29
31
  setPageJson(text) {
30
- const { page, problems } = readPage(text);
32
+ const { page, problems } = readPage(text, words);
31
33
  if (!page)
32
34
  return { ok: false, problems };
33
35
  // The page as it is already: nothing to undo.
@@ -1 +1 @@
1
- {"version":3,"file":"page-json.js","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/page-json.ts"],"names":[],"mappings":";;AA8BA,gCAEC;AAGD,4BASC;AAaD,4CAgBC;AAzED,wCAAwD;AAExD,2CAAuE;AACvE,qCAAkC;AA0BlC,oFAAoF;AACpF,SAAgB,UAAU,CAAC,IAAU;IACnC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,4EAA4E;AAC5E,SAAgB,QAAQ,CAAC,IAAY,EAAE,QAAuB,OAAE;IAC9D,MAAM,IAAI,GAAG,IAAA,oBAAQ,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5F,MAAM,OAAO,GAAG,IAAA,mBAAY,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAChG,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAA,mBAAO,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACxI,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAChE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACtE,CAAC;AAaD,SAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAgB;IAC/D,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACrC,WAAW,CAAC,IAAI;YACd,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;YAC1C,8CAA8C;YAC9C,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YACpE,2EAA2E;YAC3E,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACd,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,OAAQ,KAA4C,CAAC,GAAG,CAAC,CAAC;gBAChG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"page-json.js","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/page-json.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { validatePage } from '@fieldia/core';
2
2
  import { placeOf, readJson } from './json-text.mjs';
3
3
  import { en } from './locales/en/index.mjs';
4
+ import { settingRefusal } from './setting-refusals.mjs';
4
5
  /** The page as JSON: two spaces deep, its keys in the order the page keeps them. */
5
6
  export function pageToJson(page) {
6
7
  return JSON.stringify(page, null, 2);
@@ -13,16 +14,17 @@ export function readPage(text, words = en) {
13
14
  const checked = validatePage(read.value);
14
15
  if (checked.ok)
15
16
  return { value: read.value, tree: read.tree, page: checked.page, problems: [] };
16
- const problems = checked.issues.map((issue) => ({ ...placeOf(text, read.tree, issue.path), path: issue.path, message: issue.message }));
17
+ // A number setting's problem in its own words: "Minutes is a whole number from 1 to 120", not the format's English.
18
+ const problems = checked.issues.map((issue) => ({ ...placeOf(text, read.tree, issue.path), path: issue.path, message: settingRefusal(issue.path, words) ?? issue.message }));
17
19
  // In reading order, as the person meets them going down the text.
18
20
  problems.sort((a, b) => a.line - b.line || a.column - b.column);
19
21
  return { value: read.value, tree: read.tree, page: null, problems };
20
22
  }
21
- export function pageJsonCommands({ getPage, apply }) {
23
+ export function pageJsonCommands({ getPage, apply, words = en }) {
22
24
  return {
23
25
  pageJson: () => pageToJson(getPage()),
24
26
  setPageJson(text) {
25
- const { page, problems } = readPage(text);
27
+ const { page, problems } = readPage(text, words);
26
28
  if (!page)
27
29
  return { ok: false, problems };
28
30
  // The page as it is already: nothing to undo.
@@ -1 +1 @@
1
- {"version":3,"file":"page-json.mjs","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/page-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAa,MAAM,eAAe,CAAC;AAExD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAyB,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AA0BlC,oFAAoF;AACpF,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,QAAuB,EAAE;IAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5F,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAChG,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACxI,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAChE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACtE,CAAC;AAaD,MAAM,UAAU,gBAAgB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAgB;IAC/D,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACrC,WAAW,CAAC,IAAI;YACd,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;YAC1C,8CAA8C;YAC9C,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YACpE,2EAA2E;YAC3E,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACd,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,OAAQ,KAA4C,CAAC,GAAG,CAAC,CAAC;gBAChG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"page-json.mjs","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/page-json.ts"],"names":[],"mappings":"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"}