@fieldia/widgets 0.2.0 → 0.4.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 (91) hide show
  1. package/package.json +2 -2
  2. package/src/index.d.mts +8 -0
  3. package/src/index.d.ts +8 -0
  4. package/src/index.js +8 -0
  5. package/src/index.js.map +1 -1
  6. package/src/index.mjs +8 -0
  7. package/src/index.mjs.map +1 -1
  8. package/src/lib/calendar.d.mts +11 -0
  9. package/src/lib/calendar.d.ts +11 -0
  10. package/src/lib/calendar.js +242 -0
  11. package/src/lib/calendar.js.map +1 -0
  12. package/src/lib/calendar.mjs +238 -0
  13. package/src/lib/calendar.mjs.map +1 -0
  14. package/src/lib/display.d.mts +6 -0
  15. package/src/lib/display.d.ts +6 -0
  16. package/src/lib/display.js +60 -0
  17. package/src/lib/display.js.map +1 -0
  18. package/src/lib/display.mjs +57 -0
  19. package/src/lib/display.mjs.map +1 -0
  20. package/src/lib/extras.d.mts +3 -1
  21. package/src/lib/extras.d.ts +3 -1
  22. package/src/lib/extras.js +187 -5
  23. package/src/lib/extras.js.map +1 -1
  24. package/src/lib/extras.mjs +186 -5
  25. package/src/lib/extras.mjs.map +1 -1
  26. package/src/lib/label.d.mts +2 -0
  27. package/src/lib/label.d.ts +2 -0
  28. package/src/lib/label.js +47 -0
  29. package/src/lib/label.js.map +1 -0
  30. package/src/lib/label.mjs +43 -0
  31. package/src/lib/label.mjs.map +1 -0
  32. package/src/lib/labels.d.mts +37 -0
  33. package/src/lib/labels.d.ts +37 -0
  34. package/src/lib/labels.js +116 -0
  35. package/src/lib/labels.js.map +1 -1
  36. package/src/lib/labels.mjs +116 -0
  37. package/src/lib/labels.mjs.map +1 -1
  38. package/src/lib/lines.d.mts +5 -0
  39. package/src/lib/lines.d.ts +5 -0
  40. package/src/lib/lines.js +94 -37
  41. package/src/lib/lines.js.map +1 -1
  42. package/src/lib/lines.mjs +93 -38
  43. package/src/lib/lines.mjs.map +1 -1
  44. package/src/lib/numbers.d.mts +8 -0
  45. package/src/lib/numbers.d.ts +8 -0
  46. package/src/lib/numbers.js +47 -0
  47. package/src/lib/numbers.js.map +1 -0
  48. package/src/lib/numbers.mjs +43 -0
  49. package/src/lib/numbers.mjs.map +1 -0
  50. package/src/lib/preferences.d.mts +14 -0
  51. package/src/lib/preferences.d.ts +14 -0
  52. package/src/lib/preferences.js +44 -0
  53. package/src/lib/preferences.js.map +1 -0
  54. package/src/lib/preferences.mjs +40 -0
  55. package/src/lib/preferences.mjs.map +1 -0
  56. package/src/lib/progress.d.mts +2 -0
  57. package/src/lib/progress.d.ts +2 -0
  58. package/src/lib/progress.js +73 -0
  59. package/src/lib/progress.js.map +1 -0
  60. package/src/lib/progress.mjs +69 -0
  61. package/src/lib/progress.mjs.map +1 -0
  62. package/src/lib/properties.d.mts +2 -0
  63. package/src/lib/properties.d.ts +2 -0
  64. package/src/lib/properties.js +86 -0
  65. package/src/lib/properties.js.map +1 -0
  66. package/src/lib/properties.mjs +82 -0
  67. package/src/lib/properties.mjs.map +1 -0
  68. package/src/lib/relations.d.mts +7 -0
  69. package/src/lib/relations.d.ts +7 -0
  70. package/src/lib/relations.js +142 -22
  71. package/src/lib/relations.js.map +1 -1
  72. package/src/lib/relations.mjs +140 -21
  73. package/src/lib/relations.mjs.map +1 -1
  74. package/src/lib/statusbar.d.mts +2 -0
  75. package/src/lib/statusbar.d.ts +2 -0
  76. package/src/lib/statusbar.js +61 -0
  77. package/src/lib/statusbar.js.map +1 -0
  78. package/src/lib/statusbar.mjs +57 -0
  79. package/src/lib/statusbar.mjs.map +1 -0
  80. package/src/lib/styles.d.mts +1 -1
  81. package/src/lib/styles.d.ts +1 -1
  82. package/src/lib/styles.js +81 -3
  83. package/src/lib/styles.js.map +1 -1
  84. package/src/lib/styles.mjs +81 -3
  85. package/src/lib/styles.mjs.map +1 -1
  86. package/src/lib/widgets.d.mts +6 -1
  87. package/src/lib/widgets.d.ts +6 -1
  88. package/src/lib/widgets.js +57 -12
  89. package/src/lib/widgets.js.map +1 -1
  90. package/src/lib/widgets.mjs +58 -13
  91. package/src/lib/widgets.mjs.map +1 -1
@@ -0,0 +1,8 @@
1
+ import type { Locale } from '@fieldia/core';
2
+ /** A number at rest: "1,850,000.50", "1.850.000,50". */
3
+ export declare function formatNumber(value: number, decimals: number, locale?: Locale): string;
4
+ /**
5
+ * Typed text as a number in JavaScript's own spelling ("1234.5"), or the text
6
+ * unchanged when it is not one. Arabic-Indic digits are read as digits.
7
+ */
8
+ export declare function normalizeNumber(text: string, locale?: Locale): string;
@@ -0,0 +1,8 @@
1
+ import type { Locale } from '@fieldia/core';
2
+ /** A number at rest: "1,850,000.50", "1.850.000,50". */
3
+ export declare function formatNumber(value: number, decimals: number, locale?: Locale): string;
4
+ /**
5
+ * Typed text as a number in JavaScript's own spelling ("1234.5"), or the text
6
+ * unchanged when it is not one. Arabic-Indic digits are read as digits.
7
+ */
8
+ export declare function normalizeNumber(text: string, locale?: Locale): string;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatNumber = formatNumber;
4
+ exports.normalizeNumber = normalizeNumber;
5
+ /**
6
+ * Numbers as a reader of the page's language writes them: grouped, with a
7
+ * field's decimals, in Latin digits (as business software in Arabic shows
8
+ * them), and read back the same way. Shared by the number widget, the lines
9
+ * grid and totals.
10
+ */
11
+ const formats = new Map();
12
+ function format(locale, decimals) {
13
+ const key = `${locale}:${decimals}`;
14
+ let found = formats.get(key);
15
+ if (!found) {
16
+ found = new Intl.NumberFormat(locale, { numberingSystem: 'latn', minimumFractionDigits: decimals, maximumFractionDigits: decimals });
17
+ formats.set(key, found);
18
+ }
19
+ return found;
20
+ }
21
+ /** The language's grouping and decimal marks. */
22
+ function marks(locale) {
23
+ const parts = format(locale, 1).formatToParts(12345.6);
24
+ return { group: parts.find((p) => p.type === 'group')?.value ?? ',', decimal: parts.find((p) => p.type === 'decimal')?.value ?? '.' };
25
+ }
26
+ /** A number at rest: "1,850,000.50", "1.850.000,50". */
27
+ function formatNumber(value, decimals, locale = 'en') {
28
+ return format(locale, decimals).format(value);
29
+ }
30
+ /**
31
+ * Typed text as a number in JavaScript's own spelling ("1234.5"), or the text
32
+ * unchanged when it is not one. Arabic-Indic digits are read as digits.
33
+ */
34
+ function normalizeNumber(text, locale = 'en') {
35
+ const { group, decimal } = marks(locale);
36
+ let out = text
37
+ .replace(/[٠-٩]/g, (d) => String(d.charCodeAt(0) - 0x0660))
38
+ .replace(/[۰-۹]/g, (d) => String(d.charCodeAt(0) - 0x06f0))
39
+ .replace(/٫/g, decimal)
40
+ .replace(/٬/g, group);
41
+ // Spaces of any width group digits too (French uses a narrow no-break space).
42
+ out = out.replace(/[\s\u00a0\u202f]/g, '');
43
+ if (group.trim())
44
+ out = out.split(group).join('');
45
+ return decimal === '.' ? out : out.split(decimal).join('.');
46
+ }
47
+ //# sourceMappingURL=numbers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numbers.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/numbers.ts"],"names":[],"mappings":";;AA2BA,oCAEC;AAMD,0CAWC;AA5CD;;;;;GAKG;AAEH,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;AACrD,SAAS,MAAM,CAAC,MAAc,EAAE,QAAgB;IAC9C,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;IACpC,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,qBAAqB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrI,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iDAAiD;AACjD,SAAS,KAAK,CAAC,MAAc;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,KAAK,IAAI,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE,KAAK,IAAI,GAAG,EAAE,CAAC;AACxI,CAAC;AAED,wDAAwD;AACxD,SAAgB,YAAY,CAAC,KAAa,EAAE,QAAgB,EAAE,SAAiB,IAAI;IACjF,OAAO,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAAC,IAAY,EAAE,SAAiB,IAAI;IACjE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,GAAG,GAAG,IAAI;SACX,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;SAC1D,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;SAC1D,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxB,8EAA8E;IAC9E,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,IAAI,EAAE;QAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClD,OAAO,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Numbers as a reader of the page's language writes them: grouped, with a
3
+ * field's decimals, in Latin digits (as business software in Arabic shows
4
+ * them), and read back the same way. Shared by the number widget, the lines
5
+ * grid and totals.
6
+ */
7
+ const formats = new Map();
8
+ function format(locale, decimals) {
9
+ const key = `${locale}:${decimals}`;
10
+ let found = formats.get(key);
11
+ if (!found) {
12
+ found = new Intl.NumberFormat(locale, { numberingSystem: 'latn', minimumFractionDigits: decimals, maximumFractionDigits: decimals });
13
+ formats.set(key, found);
14
+ }
15
+ return found;
16
+ }
17
+ /** The language's grouping and decimal marks. */
18
+ function marks(locale) {
19
+ const parts = format(locale, 1).formatToParts(12345.6);
20
+ return { group: parts.find((p) => p.type === 'group')?.value ?? ',', decimal: parts.find((p) => p.type === 'decimal')?.value ?? '.' };
21
+ }
22
+ /** A number at rest: "1,850,000.50", "1.850.000,50". */
23
+ export function formatNumber(value, decimals, locale = 'en') {
24
+ return format(locale, decimals).format(value);
25
+ }
26
+ /**
27
+ * Typed text as a number in JavaScript's own spelling ("1234.5"), or the text
28
+ * unchanged when it is not one. Arabic-Indic digits are read as digits.
29
+ */
30
+ export function normalizeNumber(text, locale = 'en') {
31
+ const { group, decimal } = marks(locale);
32
+ let out = text
33
+ .replace(/[٠-٩]/g, (d) => String(d.charCodeAt(0) - 0x0660))
34
+ .replace(/[۰-۹]/g, (d) => String(d.charCodeAt(0) - 0x06f0))
35
+ .replace(/٫/g, decimal)
36
+ .replace(/٬/g, group);
37
+ // Spaces of any width group digits too (French uses a narrow no-break space).
38
+ out = out.replace(/[\s\u00a0\u202f]/g, '');
39
+ if (group.trim())
40
+ out = out.split(group).join('');
41
+ return decimal === '.' ? out : out.split(decimal).join('.');
42
+ }
43
+ //# sourceMappingURL=numbers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numbers.mjs","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/numbers.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;AACrD,SAAS,MAAM,CAAC,MAAc,EAAE,QAAgB;IAC9C,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;IACpC,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,qBAAqB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrI,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iDAAiD;AACjD,SAAS,KAAK,CAAC,MAAc;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,KAAK,IAAI,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE,KAAK,IAAI,GAAG,EAAE,CAAC;AACxI,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,QAAgB,EAAE,SAAiB,IAAI;IACjF,OAAO,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,SAAiB,IAAI;IACjE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,GAAG,GAAG,IAAI;SACX,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;SAC1D,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;SAC1D,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxB,8EAA8E;IAC9E,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,IAAI,EAAE;QAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClD,OAAO,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { JsonValue } from '@fieldia/core';
2
+ /**
3
+ * Where a person's choices about how a page looks are kept between visits:
4
+ * a table's column widths, their order, which columns show. Never data, and
5
+ * never anything a page needs to work: a store that forgets is fine.
6
+ */
7
+ export interface PreferenceStore {
8
+ get(key: string): JsonValue | null;
9
+ set(key: string, value: JsonValue): void;
10
+ }
11
+ /** Preferences in the browser's local storage, under `fieldia:`. A browser that refuses storage just forgets. */
12
+ export declare function browserPreferences(storage?: Storage): PreferenceStore;
13
+ /** Preferences that last as long as the page: for tests, and apps that keep nothing. */
14
+ export declare function memoryPreferences(): PreferenceStore;
@@ -0,0 +1,14 @@
1
+ import type { JsonValue } from '@fieldia/core';
2
+ /**
3
+ * Where a person's choices about how a page looks are kept between visits:
4
+ * a table's column widths, their order, which columns show. Never data, and
5
+ * never anything a page needs to work: a store that forgets is fine.
6
+ */
7
+ export interface PreferenceStore {
8
+ get(key: string): JsonValue | null;
9
+ set(key: string, value: JsonValue): void;
10
+ }
11
+ /** Preferences in the browser's local storage, under `fieldia:`. A browser that refuses storage just forgets. */
12
+ export declare function browserPreferences(storage?: Storage): PreferenceStore;
13
+ /** Preferences that last as long as the page: for tests, and apps that keep nothing. */
14
+ export declare function memoryPreferences(): PreferenceStore;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.browserPreferences = browserPreferences;
4
+ exports.memoryPreferences = memoryPreferences;
5
+ /** Preferences in the browser's local storage, under `fieldia:`. A browser that refuses storage just forgets. */
6
+ function browserPreferences(storage) {
7
+ const area = () => {
8
+ try {
9
+ return storage ?? globalThis.localStorage ?? null;
10
+ }
11
+ catch {
12
+ return null; // reading localStorage itself throws where site data is blocked
13
+ }
14
+ };
15
+ return {
16
+ get(key) {
17
+ try {
18
+ const text = area()?.getItem(`fieldia:${key}`);
19
+ return text == null ? null : JSON.parse(text);
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ },
25
+ set(key, value) {
26
+ try {
27
+ area()?.setItem(`fieldia:${key}`, JSON.stringify(value));
28
+ }
29
+ catch {
30
+ // Full, private or blocked: the choice lasts until the page closes.
31
+ }
32
+ },
33
+ };
34
+ }
35
+ /** Preferences that last as long as the page: for tests, and apps that keep nothing. */
36
+ function memoryPreferences() {
37
+ const values = new Map();
38
+ return {
39
+ get: (key) => (values.has(key) ? structuredCloneSafe(values.get(key)) : null),
40
+ set: (key, value) => void values.set(key, structuredCloneSafe(value)),
41
+ };
42
+ }
43
+ const structuredCloneSafe = (value) => JSON.parse(JSON.stringify(value));
44
+ //# sourceMappingURL=preferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferences.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/preferences.ts"],"names":[],"mappings":";;AAaA,gDAyBC;AAGD,8CAMC;AAnCD,iHAAiH;AACjH,SAAgB,kBAAkB,CAAC,OAAiB;IAClD,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,CAAC;YACH,OAAO,OAAO,IAAI,UAAU,CAAC,YAAY,IAAI,IAAI,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,CAAC,gEAAgE;QAC/E,CAAC;IACH,CAAC,CAAC;IACF,OAAO;QACL,GAAG,CAAC,GAAG;YACL,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,EAAE,EAAE,OAAO,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;gBAC/C,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,GAAG,CAAC,GAAG,EAAE,KAAK;YACZ,IAAI,CAAC;gBACH,IAAI,EAAE,EAAE,OAAO,CAAC,WAAW,GAAG,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3D,CAAC;YAAC,MAAM,CAAC;gBACP,oEAAoE;YACtE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,wFAAwF;AACxF,SAAgB,iBAAiB;IAC/B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC5C,OAAO;QACL,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1F,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;KACtE,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAG,CAAC,KAAgB,EAAa,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAc,CAAC"}
@@ -0,0 +1,40 @@
1
+ /** Preferences in the browser's local storage, under `fieldia:`. A browser that refuses storage just forgets. */
2
+ export function browserPreferences(storage) {
3
+ const area = () => {
4
+ try {
5
+ return storage ?? globalThis.localStorage ?? null;
6
+ }
7
+ catch {
8
+ return null; // reading localStorage itself throws where site data is blocked
9
+ }
10
+ };
11
+ return {
12
+ get(key) {
13
+ try {
14
+ const text = area()?.getItem(`fieldia:${key}`);
15
+ return text == null ? null : JSON.parse(text);
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ },
21
+ set(key, value) {
22
+ try {
23
+ area()?.setItem(`fieldia:${key}`, JSON.stringify(value));
24
+ }
25
+ catch {
26
+ // Full, private or blocked: the choice lasts until the page closes.
27
+ }
28
+ },
29
+ };
30
+ }
31
+ /** Preferences that last as long as the page: for tests, and apps that keep nothing. */
32
+ export function memoryPreferences() {
33
+ const values = new Map();
34
+ return {
35
+ get: (key) => (values.has(key) ? structuredCloneSafe(values.get(key)) : null),
36
+ set: (key, value) => void values.set(key, structuredCloneSafe(value)),
37
+ };
38
+ }
39
+ const structuredCloneSafe = (value) => JSON.parse(JSON.stringify(value));
40
+ //# sourceMappingURL=preferences.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferences.mjs","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/preferences.ts"],"names":[],"mappings":"AAYA,iHAAiH;AACjH,MAAM,UAAU,kBAAkB,CAAC,OAAiB;IAClD,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,CAAC;YACH,OAAO,OAAO,IAAI,UAAU,CAAC,YAAY,IAAI,IAAI,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,CAAC,gEAAgE;QAC/E,CAAC;IACH,CAAC,CAAC;IACF,OAAO;QACL,GAAG,CAAC,GAAG;YACL,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,EAAE,EAAE,OAAO,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;gBAC/C,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,GAAG,CAAC,GAAG,EAAE,KAAK;YACZ,IAAI,CAAC;gBACH,IAAI,EAAE,EAAE,OAAO,CAAC,WAAW,GAAG,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3D,CAAC;YAAC,MAAM,CAAC;gBACP,oEAAoE;YACtE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,iBAAiB;IAC/B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC5C,OAAO;QACL,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1F,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;KACtE,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAG,CAAC,KAAgB,EAAa,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { type WidgetFactory } from './widgets.mjs';
2
+ export declare const progressbarWidget: WidgetFactory;
@@ -0,0 +1,2 @@
1
+ import { type WidgetFactory } from './widgets';
2
+ export declare const progressbarWidget: WidgetFactory;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.progressbarWidget = void 0;
4
+ const widgets_1 = require("./widgets");
5
+ /**
6
+ * A number shown as a bar that fills towards a maximum, coloured by how far
7
+ * it has come: red under 30 %, yellow under 70 %, green from there. Options:
8
+ *
9
+ * max the maximum, 100 by default (min 0)
10
+ * maxField a number field that holds the maximum instead
11
+ * color "auto", or always "success", "warning", "danger" or "info"
12
+ * showPercent false to leave the percentage off the bar
13
+ * editable true for a box beside the bar to type the value in
14
+ */
15
+ const percents = new Map();
16
+ function percent(value, locale) {
17
+ let format = percents.get(locale);
18
+ if (!format) {
19
+ format = new Intl.NumberFormat(locale, { style: 'percent', maximumFractionDigits: 0, numberingSystem: 'latn' });
20
+ percents.set(locale, format);
21
+ }
22
+ return format.format(value / 100);
23
+ }
24
+ const progressbarWidget = (context) => {
25
+ const { node, id, document, locale = 'en' } = context;
26
+ const options = node.options ?? {};
27
+ const min = typeof options['min'] === 'number' ? options['min'] : 0;
28
+ const fixedMax = typeof options['max'] === 'number' ? options['max'] : 100;
29
+ const maxField = typeof options['maxField'] === 'string' ? options['maxField'] : null;
30
+ const color = typeof options['color'] === 'string' ? options['color'] : 'auto';
31
+ const showPercent = options['showPercent'] !== false;
32
+ const bar = document.createElement('div');
33
+ bar.className = 'fd-progressbar';
34
+ bar.setAttribute('role', 'progressbar');
35
+ const fill = document.createElement('div');
36
+ fill.className = 'fd-progressbar-fill';
37
+ const text = document.createElement('span');
38
+ text.className = 'fd-progressbar-text';
39
+ bar.append(fill, text);
40
+ // Editable: the field's own number box takes the value; the bar beside it only shows it.
41
+ let box = null;
42
+ let element = bar;
43
+ if (options['editable'] === true) {
44
+ box = (0, widgets_1.createWidget)({ ...context, node: { ...node, widget: undefined } });
45
+ bar.setAttribute('aria-hidden', 'true');
46
+ element = document.createElement('div');
47
+ element.className = 'fd-progressbar-edit';
48
+ element.append(bar, box.element);
49
+ }
50
+ else {
51
+ bar.id = id;
52
+ }
53
+ return {
54
+ element,
55
+ focus: () => box?.focus(),
56
+ update(state) {
57
+ const value = typeof state.value === 'number' ? state.value : 0;
58
+ const max = maxField ? Number(state.values[maxField] ?? 0) : fixedMax;
59
+ const share = max > min ? Math.min(100, Math.max(0, ((value - min) / (max - min)) * 100)) : 0;
60
+ const rounded = Math.round(share * 10) / 10;
61
+ fill.style.width = `${rounded}%`;
62
+ bar.setAttribute('aria-valuenow', String(value));
63
+ bar.setAttribute('aria-valuemin', String(min));
64
+ bar.setAttribute('aria-valuemax', String(max));
65
+ bar.setAttribute('aria-valuetext', percent(share, locale));
66
+ text.textContent = showPercent ? percent(share, locale) : '';
67
+ bar.dataset['tone'] = color !== 'auto' ? color : share < 30 ? 'danger' : share < 70 ? 'warning' : 'success';
68
+ box?.update(state);
69
+ },
70
+ };
71
+ };
72
+ exports.progressbarWidget = progressbarWidget;
73
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/progress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { createWidget } from './widgets.mjs';
2
+ /**
3
+ * A number shown as a bar that fills towards a maximum, coloured by how far
4
+ * it has come: red under 30 %, yellow under 70 %, green from there. Options:
5
+ *
6
+ * max the maximum, 100 by default (min 0)
7
+ * maxField a number field that holds the maximum instead
8
+ * color "auto", or always "success", "warning", "danger" or "info"
9
+ * showPercent false to leave the percentage off the bar
10
+ * editable true for a box beside the bar to type the value in
11
+ */
12
+ const percents = new Map();
13
+ function percent(value, locale) {
14
+ let format = percents.get(locale);
15
+ if (!format) {
16
+ format = new Intl.NumberFormat(locale, { style: 'percent', maximumFractionDigits: 0, numberingSystem: 'latn' });
17
+ percents.set(locale, format);
18
+ }
19
+ return format.format(value / 100);
20
+ }
21
+ export const progressbarWidget = (context) => {
22
+ const { node, id, document, locale = 'en' } = context;
23
+ const options = node.options ?? {};
24
+ const min = typeof options['min'] === 'number' ? options['min'] : 0;
25
+ const fixedMax = typeof options['max'] === 'number' ? options['max'] : 100;
26
+ const maxField = typeof options['maxField'] === 'string' ? options['maxField'] : null;
27
+ const color = typeof options['color'] === 'string' ? options['color'] : 'auto';
28
+ const showPercent = options['showPercent'] !== false;
29
+ const bar = document.createElement('div');
30
+ bar.className = 'fd-progressbar';
31
+ bar.setAttribute('role', 'progressbar');
32
+ const fill = document.createElement('div');
33
+ fill.className = 'fd-progressbar-fill';
34
+ const text = document.createElement('span');
35
+ text.className = 'fd-progressbar-text';
36
+ bar.append(fill, text);
37
+ // Editable: the field's own number box takes the value; the bar beside it only shows it.
38
+ let box = null;
39
+ let element = bar;
40
+ if (options['editable'] === true) {
41
+ box = createWidget({ ...context, node: { ...node, widget: undefined } });
42
+ bar.setAttribute('aria-hidden', 'true');
43
+ element = document.createElement('div');
44
+ element.className = 'fd-progressbar-edit';
45
+ element.append(bar, box.element);
46
+ }
47
+ else {
48
+ bar.id = id;
49
+ }
50
+ return {
51
+ element,
52
+ focus: () => box?.focus(),
53
+ update(state) {
54
+ const value = typeof state.value === 'number' ? state.value : 0;
55
+ const max = maxField ? Number(state.values[maxField] ?? 0) : fixedMax;
56
+ const share = max > min ? Math.min(100, Math.max(0, ((value - min) / (max - min)) * 100)) : 0;
57
+ const rounded = Math.round(share * 10) / 10;
58
+ fill.style.width = `${rounded}%`;
59
+ bar.setAttribute('aria-valuenow', String(value));
60
+ bar.setAttribute('aria-valuemin', String(min));
61
+ bar.setAttribute('aria-valuemax', String(max));
62
+ bar.setAttribute('aria-valuetext', percent(share, locale));
63
+ text.textContent = showPercent ? percent(share, locale) : '';
64
+ bar.dataset['tone'] = color !== 'auto' ? color : share < 30 ? 'danger' : share < 70 ? 'warning' : 'success';
65
+ box?.update(state);
66
+ },
67
+ };
68
+ };
69
+ //# sourceMappingURL=progress.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.mjs","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/progress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type WidgetFactory } from './widgets.mjs';
2
+ export declare const propertiesWidget: WidgetFactory;
@@ -0,0 +1,2 @@
1
+ import { type WidgetFactory } from './widgets';
2
+ export declare const propertiesWidget: WidgetFactory;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.propertiesWidget = void 0;
4
+ const widgets_1 = require("./widgets");
5
+ /**
6
+ * A properties field, one row per property, each edited with the widget for
7
+ * its type: text, numbers, yes/no, a choice, a date. The field's `definitions`
8
+ * say which properties there are; without them, each property is worked out
9
+ * from its value. The properties stay one value: an object by property name.
10
+ */
11
+ /** "lift_access" → "Lift access". */
12
+ const humanize = (name) => {
13
+ const words = name.replace(/_/g, ' ').trim();
14
+ return words.charAt(0).toUpperCase() + words.slice(1);
15
+ };
16
+ /** A property's type, from what it holds. */
17
+ function guess(name, value) {
18
+ const label = humanize(name);
19
+ if (typeof value === 'boolean')
20
+ return { name, label, type: 'boolean' };
21
+ if (typeof value === 'number')
22
+ return { name, label, type: Number.isInteger(value) ? 'integer' : 'float' };
23
+ if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value))
24
+ return { name, label, type: 'date' };
25
+ return { name, label, type: 'char' };
26
+ }
27
+ const propertiesWidget = (context) => {
28
+ const { form, name, field, node, id, document } = context;
29
+ const declared = field.type === 'properties' ? field.definitions : undefined;
30
+ const current = () => {
31
+ const value = form.getState().values[name];
32
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
33
+ };
34
+ // Each property's widget sees the properties as its record, and writes into them.
35
+ const properties = {
36
+ ...form,
37
+ getState: () => ({ ...form.getState(), values: current() }),
38
+ // Property values are plain JSON: text, numbers, yes/no, a choice, a date.
39
+ setValue: (property, value) => form.setValue(name, { ...current(), [property]: value }),
40
+ };
41
+ const element = document.createElement('div');
42
+ element.className = 'fd-properties';
43
+ element.setAttribute('role', 'group');
44
+ let rows = [];
45
+ let drawn = '';
46
+ function draw(definitions) {
47
+ for (const row of rows)
48
+ row.widget.destroy?.();
49
+ rows = definitions.map((definition) => {
50
+ const rowId = `${id}-${definition.name}`;
51
+ const propertyField = { type: definition.type, label: definition.label, ...(definition.options ? { options: definition.options } : {}) };
52
+ const propertyNode = { type: 'field', id: `${node.id}.${definition.name}`, field: definition.name };
53
+ const widget = (0, widgets_1.createWidget)({ ...context, form: properties, name: definition.name, field: propertyField, node: propertyNode, id: rowId });
54
+ return { definition, widget };
55
+ });
56
+ element.replaceChildren(...rows.map(({ definition, widget }) => {
57
+ const row = document.createElement('div');
58
+ row.className = 'fd-property';
59
+ row.dataset['type'] = definition.type;
60
+ const label = document.createElement('label');
61
+ label.htmlFor = `${id}-${definition.name}`;
62
+ label.textContent = definition.label;
63
+ row.append(label, widget.element);
64
+ return row;
65
+ }));
66
+ }
67
+ return {
68
+ element,
69
+ focus: () => rows[0]?.widget.focus(),
70
+ destroy: () => rows.forEach((row) => row.widget.destroy?.()),
71
+ update(state) {
72
+ const values = current();
73
+ const definitions = declared ?? Object.keys(values).map((key) => guess(key, values[key]));
74
+ const key = JSON.stringify(definitions);
75
+ if (key !== drawn) {
76
+ drawn = key;
77
+ draw(definitions);
78
+ }
79
+ for (const { definition, widget } of rows) {
80
+ widget.update({ value: values[definition.name] ?? null, values, readonly: state.readonly, required: false, invalid: false });
81
+ }
82
+ },
83
+ };
84
+ };
85
+ exports.propertiesWidget = propertiesWidget;
86
+ //# sourceMappingURL=properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"properties.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/properties.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { createWidget } from './widgets.mjs';
2
+ /**
3
+ * A properties field, one row per property, each edited with the widget for
4
+ * its type: text, numbers, yes/no, a choice, a date. The field's `definitions`
5
+ * say which properties there are; without them, each property is worked out
6
+ * from its value. The properties stay one value: an object by property name.
7
+ */
8
+ /** "lift_access" → "Lift access". */
9
+ const humanize = (name) => {
10
+ const words = name.replace(/_/g, ' ').trim();
11
+ return words.charAt(0).toUpperCase() + words.slice(1);
12
+ };
13
+ /** A property's type, from what it holds. */
14
+ function guess(name, value) {
15
+ const label = humanize(name);
16
+ if (typeof value === 'boolean')
17
+ return { name, label, type: 'boolean' };
18
+ if (typeof value === 'number')
19
+ return { name, label, type: Number.isInteger(value) ? 'integer' : 'float' };
20
+ if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value))
21
+ return { name, label, type: 'date' };
22
+ return { name, label, type: 'char' };
23
+ }
24
+ export const propertiesWidget = (context) => {
25
+ const { form, name, field, node, id, document } = context;
26
+ const declared = field.type === 'properties' ? field.definitions : undefined;
27
+ const current = () => {
28
+ const value = form.getState().values[name];
29
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
30
+ };
31
+ // Each property's widget sees the properties as its record, and writes into them.
32
+ const properties = {
33
+ ...form,
34
+ getState: () => ({ ...form.getState(), values: current() }),
35
+ // Property values are plain JSON: text, numbers, yes/no, a choice, a date.
36
+ setValue: (property, value) => form.setValue(name, { ...current(), [property]: value }),
37
+ };
38
+ const element = document.createElement('div');
39
+ element.className = 'fd-properties';
40
+ element.setAttribute('role', 'group');
41
+ let rows = [];
42
+ let drawn = '';
43
+ function draw(definitions) {
44
+ for (const row of rows)
45
+ row.widget.destroy?.();
46
+ rows = definitions.map((definition) => {
47
+ const rowId = `${id}-${definition.name}`;
48
+ const propertyField = { type: definition.type, label: definition.label, ...(definition.options ? { options: definition.options } : {}) };
49
+ const propertyNode = { type: 'field', id: `${node.id}.${definition.name}`, field: definition.name };
50
+ const widget = createWidget({ ...context, form: properties, name: definition.name, field: propertyField, node: propertyNode, id: rowId });
51
+ return { definition, widget };
52
+ });
53
+ element.replaceChildren(...rows.map(({ definition, widget }) => {
54
+ const row = document.createElement('div');
55
+ row.className = 'fd-property';
56
+ row.dataset['type'] = definition.type;
57
+ const label = document.createElement('label');
58
+ label.htmlFor = `${id}-${definition.name}`;
59
+ label.textContent = definition.label;
60
+ row.append(label, widget.element);
61
+ return row;
62
+ }));
63
+ }
64
+ return {
65
+ element,
66
+ focus: () => rows[0]?.widget.focus(),
67
+ destroy: () => rows.forEach((row) => row.widget.destroy?.()),
68
+ update(state) {
69
+ const values = current();
70
+ const definitions = declared ?? Object.keys(values).map((key) => guess(key, values[key]));
71
+ const key = JSON.stringify(definitions);
72
+ if (key !== drawn) {
73
+ drawn = key;
74
+ draw(definitions);
75
+ }
76
+ for (const { definition, widget } of rows) {
77
+ widget.update({ value: values[definition.name] ?? null, values, readonly: state.readonly, required: false, invalid: false });
78
+ }
79
+ },
80
+ };
81
+ };
82
+ //# sourceMappingURL=properties.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"properties.mjs","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/properties.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,13 @@
1
1
  import type { WidgetFactory } from './widgets.mjs';
2
2
  export declare const many2oneWidget: WidgetFactory;
3
3
  export declare const tagsWidget: WidgetFactory;
4
+ /**
5
+ * Free-text tags on a text field, kept as "oak, glass": Enter or a comma adds
6
+ * what was typed, Backspace in an empty box takes the last one away, and the
7
+ * node's `options.suggestions` are offered as you type. `options.separator`
8
+ * is "," unless set.
9
+ */
10
+ export declare const charTagsWidget: WidgetFactory;
4
11
  /** Every record as a checkbox. For short lists: it loads up to 50. */
5
12
  export declare const linkCheckboxesWidget: WidgetFactory;
6
13
  export declare const referenceWidget: WidgetFactory;