@panneau/fields 5.0.0-alpha.15 → 5.0.0-alpha.16

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 (139) hide show
  1. package/README.md +53 -3
  2. package/dist/address/AddressField.css +44 -0
  3. package/dist/address/AddressField.d.ts +37 -0
  4. package/dist/address/AddressField.d.ts.map +1 -0
  5. package/dist/address/AddressField.js +411 -0
  6. package/dist/address/AddressField.js.map +1 -0
  7. package/dist/address/AddressField.module.js +22 -0
  8. package/dist/address/AddressField.module.js.map +1 -0
  9. package/dist/address/address.d.ts +23 -0
  10. package/dist/address/address.d.ts.map +1 -0
  11. package/dist/address/address.js +58 -0
  12. package/dist/address/address.js.map +1 -0
  13. package/dist/address/index.d.ts +3 -0
  14. package/dist/address/index.d.ts.map +1 -0
  15. package/dist/address/index.js +3 -0
  16. package/dist/color/ColorField.css +9 -0
  17. package/dist/color/ColorField.d.ts +10 -3
  18. package/dist/color/ColorField.d.ts.map +1 -1
  19. package/dist/color/ColorField.js +341 -81
  20. package/dist/color/ColorField.js.map +1 -1
  21. package/dist/color/ColorField.module.js +4 -2
  22. package/dist/color/ColorField.module.js.map +1 -1
  23. package/dist/color/index.d.ts +1 -0
  24. package/dist/color/index.d.ts.map +1 -1
  25. package/dist/color/index.js +3 -1
  26. package/dist/color/palette.d.ts +23 -0
  27. package/dist/color/palette.d.ts.map +1 -0
  28. package/dist/color/palette.js +34 -0
  29. package/dist/color/palette.js.map +1 -0
  30. package/dist/country/CountryField.css +42 -0
  31. package/dist/country/CountryField.d.ts +19 -4
  32. package/dist/country/CountryField.d.ts.map +1 -1
  33. package/dist/country/CountryField.js +355 -82
  34. package/dist/country/CountryField.js.map +1 -1
  35. package/dist/country/CountryField.module.js +20 -0
  36. package/dist/country/CountryField.module.js.map +1 -0
  37. package/dist/country/index.d.ts +1 -1
  38. package/dist/country/index.d.ts.map +1 -1
  39. package/dist/daterange/DateRangeField.css +9 -0
  40. package/dist/daterange/DateRangeField.d.ts +31 -0
  41. package/dist/daterange/DateRangeField.d.ts.map +1 -0
  42. package/dist/daterange/DateRangeField.js +372 -0
  43. package/dist/daterange/DateRangeField.js.map +1 -0
  44. package/dist/daterange/DateRangeField.module.js +12 -0
  45. package/dist/daterange/DateRangeField.module.js.map +1 -0
  46. package/dist/daterange/index.d.ts +3 -0
  47. package/dist/daterange/index.d.ts.map +1 -0
  48. package/dist/daterange/index.js +3 -0
  49. package/dist/daterange/range.d.ts +61 -0
  50. package/dist/daterange/range.d.ts.map +1 -0
  51. package/dist/daterange/range.js +119 -0
  52. package/dist/daterange/range.js.map +1 -0
  53. package/dist/duration/DurationField.css +1 -1
  54. package/dist/duration/DurationField.d.ts +54 -13
  55. package/dist/duration/DurationField.d.ts.map +1 -1
  56. package/dist/duration/DurationField.js +205 -159
  57. package/dist/duration/DurationField.js.map +1 -1
  58. package/dist/duration/DurationField.module.js.map +1 -1
  59. package/dist/duration/index.d.ts +1 -1
  60. package/dist/duration/index.d.ts.map +1 -1
  61. package/dist/duration/index.js +1 -1
  62. package/dist/embed/EmbedField.d.ts +11 -2
  63. package/dist/embed/EmbedField.d.ts.map +1 -1
  64. package/dist/embed/EmbedField.js +179 -116
  65. package/dist/embed/EmbedField.js.map +1 -1
  66. package/dist/link/LinkField.css +12 -0
  67. package/dist/link/LinkField.d.ts +38 -0
  68. package/dist/link/LinkField.d.ts.map +1 -0
  69. package/dist/link/LinkField.js +742 -0
  70. package/dist/link/LinkField.js.map +1 -0
  71. package/dist/link/LinkField.module.js +8 -0
  72. package/dist/link/LinkField.module.js.map +1 -0
  73. package/dist/link/index.d.ts +3 -0
  74. package/dist/link/index.d.ts.map +1 -0
  75. package/dist/link/index.js +3 -0
  76. package/dist/link/link.d.ts +30 -0
  77. package/dist/link/link.d.ts.map +1 -0
  78. package/dist/link/link.js +63 -0
  79. package/dist/link/link.js.map +1 -0
  80. package/dist/link/pages.d.ts +17 -0
  81. package/dist/link/pages.d.ts.map +1 -0
  82. package/dist/link/pages.js +104 -0
  83. package/dist/link/pages.js.map +1 -0
  84. package/dist/location/LocationField.d.ts.map +1 -1
  85. package/dist/location/LocationField.js +9 -85
  86. package/dist/location/LocationField.js.map +1 -1
  87. package/dist/location/nominatim.d.ts +8 -2
  88. package/dist/location/nominatim.d.ts.map +1 -1
  89. package/dist/location/nominatim.js +32 -3
  90. package/dist/location/nominatim.js.map +1 -1
  91. package/dist/location/search.d.ts +10 -0
  92. package/dist/location/search.d.ts.map +1 -0
  93. package/dist/location/search.js +83 -0
  94. package/dist/location/search.js.map +1 -0
  95. package/dist/location/types.d.ts +8 -2
  96. package/dist/location/types.d.ts.map +1 -1
  97. package/dist/money/MoneyField.d.ts +28 -0
  98. package/dist/money/MoneyField.d.ts.map +1 -0
  99. package/dist/money/MoneyField.js +269 -0
  100. package/dist/money/MoneyField.js.map +1 -0
  101. package/dist/money/index.d.ts +3 -0
  102. package/dist/money/index.d.ts.map +1 -0
  103. package/dist/money/index.js +3 -0
  104. package/dist/money/money.d.ts +27 -0
  105. package/dist/money/money.d.ts.map +1 -0
  106. package/dist/money/money.js +56 -0
  107. package/dist/money/money.js.map +1 -0
  108. package/dist/region/RegionField.js +1 -1
  109. package/dist/shared/builtIn.d.ts +3 -1
  110. package/dist/shared/builtIn.d.ts.map +1 -1
  111. package/dist/shared/builtIn.js +18 -8
  112. package/dist/shared/builtIn.js.map +1 -1
  113. package/dist/shared/dates.js +2 -2
  114. package/dist/shared/dates.js.map +1 -1
  115. package/dist/shared/flow.d.ts.map +1 -1
  116. package/dist/shared/flow.js +1 -0
  117. package/dist/shared/flow.js.map +1 -1
  118. package/dist/shared/part.d.ts +26 -0
  119. package/dist/shared/part.d.ts.map +1 -0
  120. package/dist/shared/part.js +64 -0
  121. package/dist/shared/part.js.map +1 -0
  122. package/dist/tel/TelField.css +25 -0
  123. package/dist/tel/TelField.d.ts +14 -2
  124. package/dist/tel/TelField.d.ts.map +1 -1
  125. package/dist/tel/TelField.js +246 -145
  126. package/dist/tel/TelField.js.map +1 -1
  127. package/dist/tel/TelField.module.js +12 -0
  128. package/dist/tel/TelField.module.js.map +1 -0
  129. package/dist/tel/index.d.ts +1 -1
  130. package/dist/tel/index.d.ts.map +1 -1
  131. package/dist/tel/index.js +2 -2
  132. package/dist/tel/phone.d.ts +28 -0
  133. package/dist/tel/phone.d.ts.map +1 -1
  134. package/dist/tel/phone.js +48 -1
  135. package/dist/tel/phone.js.map +1 -1
  136. package/dist/url/UrlField.d.ts.map +1 -1
  137. package/dist/url/UrlField.js +1 -1
  138. package/dist/url/UrlField.js.map +1 -1
  139. package/package.json +24 -4
@@ -0,0 +1,269 @@
1
+ import { getFieldProps, getRuleNumber, getSetting, isString } from "../shared/entry.js";
2
+ import { messages } from "../shared/messages.js";
3
+ import { CURRENCY_CODES, getCurrencyName, getMoneyFormatOptions, isMoneyValue, toMoneyValue } from "./money.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { fromMinorUnits } from "@panneau/protocol/runtime";
6
+ import { useState } from "react";
7
+ import { NumberInput, Select, usePanneauIntl } from "@panneau/ui";
8
+ import { jsx } from "react/jsx-runtime";
9
+ //#region src/money/MoneyField.tsx
10
+ /**
11
+ * An amount and its currency, `{ amount, currency }`, with the amount in minor units (decision
12
+ * 0053): typed in the currency format of the locale, with the digits of the currency, and turned
13
+ * into minor units without floating point errors. A fixed `currency` shows in the amount; otherwise
14
+ * a menu after the amount picks it. Clearing the amount gives `null`.
15
+ */
16
+ function MoneyField(t0) {
17
+ const $ = c(54);
18
+ let currencies;
19
+ let disabled;
20
+ let fixed;
21
+ let max;
22
+ let min;
23
+ let onChange;
24
+ let props;
25
+ let readOnly;
26
+ let required;
27
+ let value;
28
+ if ($[0] !== t0) {
29
+ ({value, onChange, currency: fixed, currencies, min, max, disabled, readOnly, required, ...props} = t0);
30
+ $[0] = t0;
31
+ $[1] = currencies;
32
+ $[2] = disabled;
33
+ $[3] = fixed;
34
+ $[4] = max;
35
+ $[5] = min;
36
+ $[6] = onChange;
37
+ $[7] = props;
38
+ $[8] = readOnly;
39
+ $[9] = required;
40
+ $[10] = value;
41
+ } else {
42
+ currencies = $[1];
43
+ disabled = $[2];
44
+ fixed = $[3];
45
+ max = $[4];
46
+ min = $[5];
47
+ onChange = $[6];
48
+ props = $[7];
49
+ readOnly = $[8];
50
+ required = $[9];
51
+ value = $[10];
52
+ }
53
+ const intl = usePanneauIntl();
54
+ const [picked, setPicked] = useState(null);
55
+ const current = isMoneyValue(value) ? value : null;
56
+ let t1;
57
+ if ($[11] !== currencies || $[12] !== fixed) {
58
+ t1 = fixed !== void 0 && fixed !== null ? [] : currencies !== void 0 && currencies !== null && currencies.length > 0 ? currencies : CURRENCY_CODES;
59
+ $[11] = currencies;
60
+ $[12] = fixed;
61
+ $[13] = t1;
62
+ } else t1 = $[13];
63
+ const choices = t1;
64
+ const currency = fixed ?? (current !== null ? current.currency : picked ?? currencies?.[0] ?? null);
65
+ const hasMenu = choices.length > 0;
66
+ let t2;
67
+ if ($[14] !== currency) {
68
+ t2 = (amount) => fromMinorUnits(amount, currency ?? "");
69
+ $[14] = currency;
70
+ $[15] = t2;
71
+ } else t2 = $[15];
72
+ const toMajor = t2;
73
+ let t3;
74
+ if ($[16] !== choices || $[17] !== currency || $[18] !== current || $[19] !== disabled || $[20] !== hasMenu || $[21] !== intl || $[22] !== onChange || $[23] !== readOnly || $[24] !== toMajor) {
75
+ t3 = hasMenu ? /* @__PURE__ */ jsx(Select, {
76
+ "aria-label": intl.formatMessage(messages.moneyCurrency),
77
+ appearance: "bare",
78
+ isRequired: true,
79
+ isDisabled: disabled === true || readOnly === true,
80
+ placeholder: intl.formatMessage(messages.moneyCurrency),
81
+ options: choices.map((code) => ({
82
+ value: code,
83
+ label: `${code} – ${getCurrencyName(code, intl.locale)}`
84
+ })),
85
+ value: currency,
86
+ renderValue: _temp,
87
+ onChange: (next) => {
88
+ const code_0 = next !== null ? String(next) : null;
89
+ setPicked(code_0);
90
+ if (current !== null) onChange?.(toMoneyValue(toMajor(current.amount), code_0));
91
+ }
92
+ }) : void 0;
93
+ $[16] = choices;
94
+ $[17] = currency;
95
+ $[18] = current;
96
+ $[19] = disabled;
97
+ $[20] = hasMenu;
98
+ $[21] = intl;
99
+ $[22] = onChange;
100
+ $[23] = readOnly;
101
+ $[24] = toMajor;
102
+ $[25] = t3;
103
+ } else t3 = $[25];
104
+ const menu = t3;
105
+ let t4;
106
+ if ($[26] !== current || $[27] !== toMajor) {
107
+ t4 = current !== null ? toMajor(current.amount) : null;
108
+ $[26] = current;
109
+ $[27] = toMajor;
110
+ $[28] = t4;
111
+ } else t4 = $[28];
112
+ let t5;
113
+ if ($[29] !== currency || $[30] !== onChange) {
114
+ t5 = (next_0) => onChange?.(next_0 === null ? null : toMoneyValue(next_0, currency));
115
+ $[29] = currency;
116
+ $[30] = onChange;
117
+ $[31] = t5;
118
+ } else t5 = $[31];
119
+ const t6 = hasMenu ? "narrowSymbol" : "symbol";
120
+ let t7;
121
+ if ($[32] !== currency || $[33] !== t6) {
122
+ t7 = getMoneyFormatOptions(currency, t6);
123
+ $[32] = currency;
124
+ $[33] = t6;
125
+ $[34] = t7;
126
+ } else t7 = $[34];
127
+ let t8;
128
+ if ($[35] !== min || $[36] !== toMajor) {
129
+ t8 = min !== void 0 ? { minValue: toMajor(min) } : {};
130
+ $[35] = min;
131
+ $[36] = toMajor;
132
+ $[37] = t8;
133
+ } else t8 = $[37];
134
+ let t9;
135
+ if ($[38] !== max || $[39] !== toMajor) {
136
+ t9 = max !== void 0 ? { maxValue: toMajor(max) } : {};
137
+ $[38] = max;
138
+ $[39] = toMajor;
139
+ $[40] = t9;
140
+ } else t9 = $[40];
141
+ let t10;
142
+ if ($[41] !== menu) {
143
+ t10 = menu !== void 0 ? { suffix: menu } : {};
144
+ $[41] = menu;
145
+ $[42] = t10;
146
+ } else t10 = $[42];
147
+ let t11;
148
+ if ($[43] !== disabled || $[44] !== props || $[45] !== readOnly || $[46] !== required || $[47] !== t10 || $[48] !== t4 || $[49] !== t5 || $[50] !== t7 || $[51] !== t8 || $[52] !== t9) {
149
+ t11 = /* @__PURE__ */ jsx(NumberInput, {
150
+ ...props,
151
+ value: t4,
152
+ onChange: t5,
153
+ formatOptions: t7,
154
+ ...t8,
155
+ ...t9,
156
+ ...t10,
157
+ isDisabled: disabled,
158
+ isReadOnly: readOnly,
159
+ isRequired: required
160
+ });
161
+ $[43] = disabled;
162
+ $[44] = props;
163
+ $[45] = readOnly;
164
+ $[46] = required;
165
+ $[47] = t10;
166
+ $[48] = t4;
167
+ $[49] = t5;
168
+ $[50] = t7;
169
+ $[51] = t8;
170
+ $[52] = t9;
171
+ $[53] = t11;
172
+ } else t11 = $[53];
173
+ return t11;
174
+ }
175
+ /** The `money` type: settings `currency` and `currencies`, `min` and `max` from its rules. */
176
+ function _temp(option) {
177
+ return String(option.value);
178
+ }
179
+ function MoneyFieldEntry(props) {
180
+ const $ = c(26);
181
+ const { field } = props;
182
+ let t0;
183
+ if ($[0] !== field) {
184
+ t0 = getRuleNumber(field, "min");
185
+ $[0] = field;
186
+ $[1] = t0;
187
+ } else t0 = $[1];
188
+ const min = t0;
189
+ let t1;
190
+ if ($[2] !== field) {
191
+ t1 = getRuleNumber(field, "max");
192
+ $[2] = field;
193
+ $[3] = t1;
194
+ } else t1 = $[3];
195
+ const max = t1;
196
+ let t2;
197
+ if ($[4] !== field) {
198
+ t2 = getSetting(field, "currency", isString);
199
+ $[4] = field;
200
+ $[5] = t2;
201
+ } else t2 = $[5];
202
+ const currency = t2;
203
+ let t3;
204
+ if ($[6] !== field) {
205
+ t3 = getSetting(field, "currencies", _temp2);
206
+ $[6] = field;
207
+ $[7] = t3;
208
+ } else t3 = $[7];
209
+ const currencies = t3;
210
+ let t4;
211
+ if ($[8] !== props) {
212
+ t4 = getFieldProps(props);
213
+ $[8] = props;
214
+ $[9] = t4;
215
+ } else t4 = $[9];
216
+ const t5 = isMoneyValue(props.value) ? props.value : null;
217
+ let t6;
218
+ if ($[10] !== currency) {
219
+ t6 = currency !== void 0 ? { currency } : {};
220
+ $[10] = currency;
221
+ $[11] = t6;
222
+ } else t6 = $[11];
223
+ let t7;
224
+ if ($[12] !== currencies) {
225
+ t7 = currencies !== void 0 ? { currencies } : {};
226
+ $[12] = currencies;
227
+ $[13] = t7;
228
+ } else t7 = $[13];
229
+ let t8;
230
+ if ($[14] !== min) {
231
+ t8 = min !== void 0 ? { min } : {};
232
+ $[14] = min;
233
+ $[15] = t8;
234
+ } else t8 = $[15];
235
+ let t9;
236
+ if ($[16] !== max) {
237
+ t9 = max !== void 0 ? { max } : {};
238
+ $[16] = max;
239
+ $[17] = t9;
240
+ } else t9 = $[17];
241
+ let t10;
242
+ if ($[18] !== props.onChange || $[19] !== t4 || $[20] !== t5 || $[21] !== t6 || $[22] !== t7 || $[23] !== t8 || $[24] !== t9) {
243
+ t10 = /* @__PURE__ */ jsx(MoneyField, {
244
+ ...t4,
245
+ value: t5,
246
+ onChange: props.onChange,
247
+ ...t6,
248
+ ...t7,
249
+ ...t8,
250
+ ...t9
251
+ });
252
+ $[18] = props.onChange;
253
+ $[19] = t4;
254
+ $[20] = t5;
255
+ $[21] = t6;
256
+ $[22] = t7;
257
+ $[23] = t8;
258
+ $[24] = t9;
259
+ $[25] = t10;
260
+ } else t10 = $[25];
261
+ return t10;
262
+ }
263
+ function _temp2(value) {
264
+ return Array.isArray(value) ? value.every(isString) : false;
265
+ }
266
+ //#endregion
267
+ export { MoneyField, MoneyFieldEntry };
268
+
269
+ //# sourceMappingURL=MoneyField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MoneyField.js","names":["useState","fromMinorUnits","NumberInput","Select","usePanneauIntl","getFieldProps","getRuleNumber","getSetting","isString","messages","FieldEntryProps","FieldProps","CURRENCY_CODES","MoneyFieldValue","getCurrencyName","getMoneyFormatOptions","isMoneyValue","toMoneyValue","MoneyFieldProps","currency","currencies","min","max","placeholder","controlClassName","inputClassName","MoneyField","t0","$","_c","disabled","fixed","onChange","props","readOnly","required","value","intl","picked","setPicked","current","t1","undefined","length","choices","hasMenu","t2","amount","toMajor","t3","formatMessage","moneyCurrency","map","code","label","locale","_temp","next","code_0","String","menu","t4","t5","next_0","t6","t7","t8","minValue","t9","maxValue","t10","suffix","t11","option","MoneyFieldEntry","field","_temp2","Array","isArray","every","_c"],"sources":["../../src/money/MoneyField.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { fromMinorUnits } from '@panneau/protocol/runtime';\nimport { NumberInput, Select, usePanneauIntl } from '@panneau/ui';\n\nimport { getFieldProps, getRuleNumber, getSetting, isString } from '../shared/entry';\nimport { messages } from '../shared/messages';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\nimport {\n CURRENCY_CODES,\n type MoneyFieldValue,\n getCurrencyName,\n getMoneyFormatOptions,\n isMoneyValue,\n toMoneyValue,\n} from './money';\n\nexport interface MoneyFieldProps extends FieldProps<MoneyFieldValue> {\n /** The currency of every amount (`CAD`): the field shows it, and can't change it. */\n currency?: string | null;\n /**\n * The currencies the user picks from, the first one for a new amount. Without `currency` or\n * `currencies`, every currency.\n */\n currencies?: readonly string[] | null;\n /** The smallest amount, in minor units. */\n min?: number;\n /** The largest amount, in minor units. */\n max?: number;\n placeholder?: string;\n controlClassName?: string;\n inputClassName?: string;\n}\n\n/**\n * An amount and its currency, `{ amount, currency }`, with the amount in minor units (decision\n * 0053): typed in the currency format of the locale, with the digits of the currency, and turned\n * into minor units without floating point errors. A fixed `currency` shows in the amount; otherwise\n * a menu after the amount picks it. Clearing the amount gives `null`.\n */\nexport function MoneyField({\n value,\n onChange,\n currency: fixed,\n currencies,\n min,\n max,\n disabled,\n readOnly,\n required,\n ...props\n}: MoneyFieldProps) {\n const intl = usePanneauIntl();\n // The currency picked before an amount is typed: the value is still `null`.\n const [picked, setPicked] = useState<string | null>(null);\n const current = isMoneyValue(value) ? value : null;\n const choices =\n fixed !== undefined && fixed !== null\n ? []\n : currencies !== undefined && currencies !== null && currencies.length > 0\n ? currencies\n : CURRENCY_CODES;\n const currency =\n fixed ?? (current !== null ? current.currency : (picked ?? currencies?.[0] ?? null));\n const hasMenu = choices.length > 0;\n const toMajor = (amount: number) => fromMinorUnits(amount, currency ?? '');\n\n const menu = hasMenu ? (\n <Select\n aria-label={intl.formatMessage(messages.moneyCurrency)}\n appearance=\"bare\"\n isRequired\n isDisabled={disabled === true || readOnly === true}\n placeholder={intl.formatMessage(messages.moneyCurrency)}\n options={choices.map((code) => ({\n value: code,\n label: `${code} – ${getCurrencyName(code, intl.locale)}`,\n }))}\n value={currency}\n renderValue={(option) => String(option.value)}\n onChange={(next) => {\n const code = next !== null ? String(next) : null;\n setPicked(code);\n if (current !== null) {\n // The same amount, in the digits of the currency picked.\n onChange?.(toMoneyValue(toMajor(current.amount), code));\n }\n }}\n />\n ) : undefined;\n\n return (\n <NumberInput\n {...props}\n value={current !== null ? toMajor(current.amount) : null}\n onChange={(next) => onChange?.(next === null ? null : toMoneyValue(next, currency))}\n formatOptions={getMoneyFormatOptions(currency, hasMenu ? 'narrowSymbol' : 'symbol')}\n {...(min !== undefined ? { minValue: toMajor(min) } : {})}\n {...(max !== undefined ? { maxValue: toMajor(max) } : {})}\n {...(menu !== undefined ? { suffix: menu } : {})}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n />\n );\n}\n\n/** The `money` type: settings `currency` and `currencies`, `min` and `max` from its rules. */\nexport function MoneyFieldEntry(props: FieldEntryProps) {\n const { field } = props;\n const min = getRuleNumber(field, 'min');\n const max = getRuleNumber(field, 'max');\n const currency = getSetting(field, 'currency', isString);\n const currencies = getSetting(field, 'currencies', (value): value is string[] =>\n Array.isArray(value) ? value.every(isString) : false,\n );\n return (\n <MoneyField\n {...getFieldProps(props)}\n value={isMoneyValue(props.value) ? props.value : null}\n onChange={props.onChange}\n {...(currency !== undefined ? { currency } : {})}\n {...(currencies !== undefined ? { currencies } : {})}\n {...(min !== undefined ? { min } : {})}\n {...(max !== undefined ? { max } : {})}\n />\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { MoneyField, MoneyFieldEntry, type MoneyFieldProps } from './MoneyField.js';
2
+ export { type MoneyFieldValue, formatMoney, getCurrencyName, getMoneyFormatOptions, isMoneyValue, toMoneyValue, } from './money.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/money/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EACH,KAAK,eAAe,EACpB,WAAW,EACX,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,YAAY,GACf,MAAM,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { formatMoney, getCurrencyName, getMoneyFormatOptions, isMoneyValue, toMoneyValue } from "./money.js";
2
+ import { MoneyField, MoneyFieldEntry } from "./MoneyField.js";
3
+ export { MoneyField, MoneyFieldEntry, formatMoney, getCurrencyName, getMoneyFormatOptions, isMoneyValue, toMoneyValue };
@@ -0,0 +1,27 @@
1
+ import { CURRENCY_CODES, fromMinorUnits, getCurrencyDigits, toMinorUnits } from '@panneau/protocol/runtime';
2
+ /**
3
+ * A `money` value as a field holds it (decision 0053): an amount in minor units, and its currency,
4
+ * `null` while an amount is typed before a currency is picked, which the `money` rule refuses.
5
+ */
6
+ export interface MoneyFieldValue {
7
+ amount: number;
8
+ currency: string | null;
9
+ }
10
+ /** Whether a value is a `money` value: an amount and a currency, as the field holds it. */
11
+ export declare function isMoneyValue(value: unknown): value is MoneyFieldValue;
12
+ /** The name of a currency in a locale (`dollar canadien`), or its code. */
13
+ export declare function getCurrencyName(code: string, locale: string): string;
14
+ /**
15
+ * The format of an amount of a currency in a locale, with the digits of the currency in ISO 4217:
16
+ * `12,50 $` for 12.50 CAD in French, `¥1,250` for JPY.
17
+ */
18
+ export declare function getMoneyFormatOptions(currency: string | null, currencyDisplay?: Intl.NumberFormatOptions['currencyDisplay']): Intl.NumberFormatOptions;
19
+ /**
20
+ * An amount in minor units with its currency, in the format of the locale: `1 250,00 $` for
21
+ * `{ "amount": 125000, "currency": "CAD" }` in French. `null` for a value that isn't money.
22
+ */
23
+ export declare function formatMoney(value: unknown, locale: string): string | null;
24
+ /** An amount typed in major units, in minor units of its currency. */
25
+ export declare function toMoneyValue(major: number, currency: string | null): MoneyFieldValue;
26
+ export { CURRENCY_CODES, fromMinorUnits, getCurrencyDigits, toMinorUnits };
27
+ //# sourceMappingURL=money.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../../src/money/money.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,cAAc,EACd,cAAc,EACd,iBAAiB,EAEjB,YAAY,EACf,MAAM,2BAA2B,CAAC;AAEnC;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAQrE;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMpE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,eAAe,GAAE,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,CAAY,GACxE,IAAI,CAAC,mBAAmB,CAS1B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYzE;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,eAAe,CAEpF;AAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { CURRENCY_CODES, fromMinorUnits as fromMinorUnits$1, getCurrencyDigits, isCurrencyCode, toMinorUnits } from "@panneau/protocol/runtime";
2
+ //#region src/money/money.ts
3
+ /** Whether a value is a `money` value: an amount and a currency, as the field holds it. */
4
+ function isMoneyValue(value) {
5
+ return typeof value === "object" && value !== null && typeof value.amount === "number" && "currency" in value && (typeof value.currency === "string" || value.currency === null);
6
+ }
7
+ /** The name of a currency in a locale (`dollar canadien`), or its code. */
8
+ function getCurrencyName(code, locale) {
9
+ try {
10
+ return new Intl.DisplayNames([locale], { type: "currency" }).of(code) ?? code;
11
+ } catch {
12
+ return code;
13
+ }
14
+ }
15
+ /**
16
+ * The format of an amount of a currency in a locale, with the digits of the currency in ISO 4217:
17
+ * `12,50 $` for 12.50 CAD in French, `¥1,250` for JPY.
18
+ */
19
+ function getMoneyFormatOptions(currency, currencyDisplay = "symbol") {
20
+ const digits = getCurrencyDigits(currency ?? "");
21
+ return {
22
+ ...currency !== null && isCurrencyCode(currency) ? {
23
+ style: "currency",
24
+ currency,
25
+ currencyDisplay
26
+ } : {},
27
+ minimumFractionDigits: digits,
28
+ maximumFractionDigits: digits
29
+ };
30
+ }
31
+ /**
32
+ * An amount in minor units with its currency, in the format of the locale: `1 250,00 $` for
33
+ * `{ "amount": 125000, "currency": "CAD" }` in French. `null` for a value that isn't money.
34
+ */
35
+ function formatMoney(value, locale) {
36
+ if (!isMoneyValue(value)) return null;
37
+ const { amount, currency } = value;
38
+ const major = fromMinorUnits$1(amount, currency ?? "");
39
+ try {
40
+ const text = new Intl.NumberFormat(locale, getMoneyFormatOptions(currency)).format(major);
41
+ return currency !== null && !isCurrencyCode(currency) ? `${text} ${currency}` : text;
42
+ } catch {
43
+ return `${String(major)} ${currency ?? ""}`.trim();
44
+ }
45
+ }
46
+ /** An amount typed in major units, in minor units of its currency. */
47
+ function toMoneyValue(major, currency) {
48
+ return {
49
+ amount: toMinorUnits(major, currency ?? ""),
50
+ currency
51
+ };
52
+ }
53
+ //#endregion
54
+ export { CURRENCY_CODES, formatMoney, fromMinorUnits$1 as fromMinorUnits, getCurrencyDigits, getCurrencyName, getMoneyFormatOptions, isMoneyValue, toMinorUnits, toMoneyValue };
55
+
56
+ //# sourceMappingURL=money.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.js","names":["CURRENCY_CODES","fromMinorUnits","getCurrencyDigits","isCurrencyCode","toMinorUnits","MoneyFieldValue","amount","currency","isMoneyValue","value","getCurrencyName","code","locale","Intl","DisplayNames","type","of","getMoneyFormatOptions","currencyDisplay","NumberFormatOptions","digits","style","minimumFractionDigits","maximumFractionDigits","formatMoney","major","text","NumberFormat","format","String","trim","toMoneyValue","fromMinorUnits"],"sources":["../../src/money/money.ts"],"sourcesContent":["import {\n CURRENCY_CODES,\n fromMinorUnits,\n getCurrencyDigits,\n isCurrencyCode,\n toMinorUnits,\n} from '@panneau/protocol/runtime';\n\n/**\n * A `money` value as a field holds it (decision 0053): an amount in minor units, and its currency,\n * `null` while an amount is typed before a currency is picked, which the `money` rule refuses.\n */\nexport interface MoneyFieldValue {\n amount: number;\n currency: string | null;\n}\n\n/** Whether a value is a `money` value: an amount and a currency, as the field holds it. */\nexport function isMoneyValue(value: unknown): value is MoneyFieldValue {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { amount?: unknown }).amount === 'number' &&\n 'currency' in value &&\n (typeof value.currency === 'string' || value.currency === null)\n );\n}\n\n/** The name of a currency in a locale (`dollar canadien`), or its code. */\nexport function getCurrencyName(code: string, locale: string): string {\n try {\n return new Intl.DisplayNames([locale], { type: 'currency' }).of(code) ?? code;\n } catch {\n return code;\n }\n}\n\n/**\n * The format of an amount of a currency in a locale, with the digits of the currency in ISO 4217:\n * `12,50 $` for 12.50 CAD in French, `¥1,250` for JPY.\n */\nexport function getMoneyFormatOptions(\n currency: string | null,\n currencyDisplay: Intl.NumberFormatOptions['currencyDisplay'] = 'symbol',\n): Intl.NumberFormatOptions {\n const digits = getCurrencyDigits(currency ?? '');\n return {\n ...(currency !== null && isCurrencyCode(currency)\n ? { style: 'currency', currency, currencyDisplay }\n : {}),\n minimumFractionDigits: digits,\n maximumFractionDigits: digits,\n };\n}\n\n/**\n * An amount in minor units with its currency, in the format of the locale: `1 250,00 $` for\n * `{ \"amount\": 125000, \"currency\": \"CAD\" }` in French. `null` for a value that isn't money.\n */\nexport function formatMoney(value: unknown, locale: string): string | null {\n if (!isMoneyValue(value)) {\n return null;\n }\n const { amount, currency } = value;\n const major = fromMinorUnits(amount, currency ?? '');\n try {\n const text = new Intl.NumberFormat(locale, getMoneyFormatOptions(currency)).format(major);\n return currency !== null && !isCurrencyCode(currency) ? `${text} ${currency}` : text;\n } catch {\n return `${String(major)} ${currency ?? ''}`.trim();\n }\n}\n\n/** An amount typed in major units, in minor units of its currency. */\nexport function toMoneyValue(major: number, currency: string | null): MoneyFieldValue {\n return { amount: toMinorUnits(major, currency ?? ''), currency };\n}\n\nexport { CURRENCY_CODES, fromMinorUnits, getCurrencyDigits, toMinorUnits };\n"],"mappings":";;;AAkBA,SAAgBQ,aAAaC,OAA0C;CACnE,OACI,OAAOA,UAAU,YACjBA,UAAU,QACV,OAAQA,MAA+BH,WAAW,YAClD,cAAcG,UACb,OAAOA,MAAMF,aAAa,YAAYE,MAAMF,aAAa;AAElE;;AAGA,SAAgBG,gBAAgBC,MAAcC,QAAwB;CAClE,IAAI;EACA,OAAO,IAAIC,KAAKC,aAAa,CAACF,MAAM,GAAG,EAAEG,MAAM,WAAW,CAAC,CAAC,CAACC,GAAGL,IAAI,KAAKA;CAC7E,QAAQ;EACJ,OAAOA;CACX;AACJ;;;;;AAMA,SAAgBM,sBACZV,UACAW,kBAA+D,UACvC;CACxB,MAAME,SAASlB,kBAAkBK,YAAY,EAAE;CAC/C,OAAO;EACH,GAAIA,aAAa,QAAQJ,eAAeI,QAAQ,IAC1C;GAAEc,OAAO;GAAYd;GAAUW;EAAgB,IAC/C,CAAC;EACPI,uBAAuBF;EACvBG,uBAAuBH;CAC3B;AACJ;;;;;AAMA,SAAgBI,YAAYf,OAAgBG,QAA+B;CACvE,IAAI,CAACJ,aAAaC,KAAK,GACnB,OAAO;CAEX,MAAM,EAAEH,QAAQC,aAAaE;CAC7B,MAAMgB,QAAQxB,iBAAeK,QAAQC,YAAY,EAAE;CACnD,IAAI;EACA,MAAMmB,OAAO,IAAIb,KAAKc,aAAaf,QAAQK,sBAAsBV,QAAQ,CAAC,CAAC,CAACqB,OAAOH,KAAK;EACxF,OAAOlB,aAAa,QAAQ,CAACJ,eAAeI,QAAQ,IAAI,GAAGmB,KAAI,GAAInB,aAAamB;CACpF,QAAQ;EACJ,OAAO,GAAGG,OAAOJ,KAAK,EAAC,GAAIlB,YAAY,KAAKuB,KAAK;CACrD;AACJ;;AAGA,SAAgBC,aAAaN,OAAelB,UAA0C;CAClF,OAAO;EAAED,QAAQF,aAAaqB,OAAOlB,YAAY,EAAE;EAAGA;CAAS;AACnE"}
@@ -1,7 +1,7 @@
1
1
  import { getFieldProps, getSetting, isString } from "../shared/entry.js";
2
2
  import { messages } from "../shared/messages.js";
3
- import { TextField } from "../text/TextField.js";
4
3
  import { CodeComboBox } from "../shared/CodeComboBox.js";
4
+ import { TextField } from "../text/TextField.js";
5
5
  import { getRegions } from "./regions.js";
6
6
  import { c } from "react/compiler-runtime";
7
7
  import { usePanneauIntl } from "@panneau/ui";
@@ -3,7 +3,9 @@ import type { FieldEntry } from './types.js';
3
3
  * The entries of the built-in field types. `richtext` and `media` come with their plugins
4
4
  * (`@panneau/editor` and `@panneau/media`): without them, `DefinitionField` renders a placeholder.
5
5
  * `file` uploads through the upload source of the fields context, or gives the files themselves.
6
- * `embed` and `location` use its embed source and its maps; `location` loads Leaflet when shown.
6
+ * `embed`, `location` and `address` use its embed source and its maps; `location` loads Leaflet
7
+ * when shown. `link` searches its pages with the relation source, and picks its files with the
8
+ * `media` entry.
7
9
  */
8
10
  export declare const builtInFields: Readonly<Record<string, FieldEntry>>;
9
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"builtIn.d.ts","sourceRoot":"","sources":["../../src/shared/builtIn.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CA0B9D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC7C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAK7D,CAAC"}
1
+ {"version":3,"file":"builtIn.d.ts","sourceRoot":"","sources":["../../src/shared/builtIn.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CA8B9D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC7C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAK7D,CAAC"}
@@ -1,8 +1,12 @@
1
- import { BooleanFieldEntry } from "../boolean/BooleanField.js";
1
+ import { CountryFieldEntry } from "../country/CountryField.js";
2
+ import { LocationFieldEntry } from "../location/LocationField.js";
2
3
  import { TextFieldEntry } from "../text/TextField.js";
4
+ import { RegionFieldEntry } from "../region/RegionField.js";
5
+ import { AddressFieldEntry } from "../address/AddressField.js";
6
+ import { BooleanFieldEntry } from "../boolean/BooleanField.js";
3
7
  import { ColorFieldEntry } from "../color/ColorField.js";
4
- import { CountryFieldEntry } from "../country/CountryField.js";
5
8
  import { DateFieldEntry } from "../date/DateField.js";
9
+ import { DateRangeFieldEntry } from "../daterange/DateRangeField.js";
6
10
  import { DateTimeFieldEntry } from "../datetime/DateTimeField.js";
7
11
  import { DurationFieldEntry } from "../duration/DurationField.js";
8
12
  import { EmailFieldEntry } from "../email/EmailField.js";
@@ -10,26 +14,28 @@ import { EmbedFieldEntry } from "../embed/EmbedField.js";
10
14
  import { FileFieldEntry } from "../file/FileField.js";
11
15
  import { GroupFieldEntry } from "../group/GroupField.js";
12
16
  import { JsonFieldEntry } from "../json/JsonField.js";
13
- import { LocationFieldEntry } from "../location/LocationField.js";
17
+ import { TelFieldEntry } from "../tel/TelField.js";
18
+ import { UrlFieldEntry } from "../url/UrlField.js";
19
+ import { LinkFieldEntry } from "../link/LinkField.js";
20
+ import { MoneyFieldEntry } from "../money/MoneyField.js";
14
21
  import { NumberFieldEntry } from "../number/NumberField.js";
15
22
  import { RangeFieldEntry } from "../range/RangeField.js";
16
- import { RegionFieldEntry } from "../region/RegionField.js";
17
23
  import { RelationFieldEntry } from "../relation/RelationField.js";
18
24
  import { RepeaterFieldEntry } from "../repeater/RepeaterField.js";
19
25
  import { SelectFieldEntry } from "../select/SelectField.js";
20
26
  import { SlugFieldEntry } from "../slug/SlugField.js";
21
27
  import { TagsFieldEntry } from "../tags/TagsField.js";
22
- import { TelFieldEntry } from "../tel/TelField.js";
23
28
  import { TextAreaFieldEntry } from "../textarea/TextAreaField.js";
24
29
  import { TimeFieldEntry } from "../time/TimeField.js";
25
- import { UrlFieldEntry } from "../url/UrlField.js";
26
30
  import { fr } from "@panneau/intl";
27
31
  //#region src/shared/builtIn.ts
28
32
  /**
29
33
  * The entries of the built-in field types. `richtext` and `media` come with their plugins
30
34
  * (`@panneau/editor` and `@panneau/media`): without them, `DefinitionField` renders a placeholder.
31
35
  * `file` uploads through the upload source of the fields context, or gives the files themselves.
32
- * `embed` and `location` use its embed source and its maps; `location` loads Leaflet when shown.
36
+ * `embed`, `location` and `address` use its embed source and its maps; `location` loads Leaflet
37
+ * when shown. `link` searches its pages with the relation source, and picks its files with the
38
+ * `media` entry.
33
39
  */
34
40
  var builtInFields = {
35
41
  text: TextFieldEntry,
@@ -56,7 +62,11 @@ var builtInFields = {
56
62
  embed: EmbedFieldEntry,
57
63
  location: LocationFieldEntry,
58
64
  country: CountryFieldEntry,
59
- region: RegionFieldEntry
65
+ region: RegionFieldEntry,
66
+ address: AddressFieldEntry,
67
+ link: LinkFieldEntry,
68
+ daterange: DateRangeFieldEntry,
69
+ money: MoneyFieldEntry
60
70
  };
61
71
  /**
62
72
  * The built-in fields as a `@panneau/core` plugin: their entries, and the French messages of
@@ -1 +1 @@
1
- {"version":3,"file":"builtIn.js","names":["fr","BooleanFieldEntry","ColorFieldEntry","CountryFieldEntry","DateFieldEntry","DateTimeFieldEntry","DurationFieldEntry","EmailFieldEntry","EmbedFieldEntry","FileFieldEntry","GroupFieldEntry","JsonFieldEntry","LocationFieldEntry","NumberFieldEntry","RangeFieldEntry","RegionFieldEntry","RelationFieldEntry","RepeaterFieldEntry","SelectFieldEntry","SlugFieldEntry","TagsFieldEntry","TelFieldEntry","TextFieldEntry","TextAreaFieldEntry","TimeFieldEntry","UrlFieldEntry","FieldEntry","builtInFields","Readonly","Record","text","textarea","number","boolean","date","datetime","time","select","email","url","color","slug","file","relation","group","repeater","tel","range","duration","json","tags","embed","location","country","region","fieldsPlugin","id","fields","locales"],"sources":["../../src/shared/builtIn.ts"],"sourcesContent":["import { fr } from '@panneau/intl';\n\nimport { BooleanFieldEntry } from '../boolean/BooleanField';\nimport { ColorFieldEntry } from '../color/ColorField';\nimport { CountryFieldEntry } from '../country/CountryField';\nimport { DateFieldEntry } from '../date/DateField';\nimport { DateTimeFieldEntry } from '../datetime/DateTimeField';\nimport { DurationFieldEntry } from '../duration/DurationField';\nimport { EmailFieldEntry } from '../email/EmailField';\nimport { EmbedFieldEntry } from '../embed/EmbedField';\nimport { FileFieldEntry } from '../file/FileField';\nimport { GroupFieldEntry } from '../group/GroupField';\nimport { JsonFieldEntry } from '../json/JsonField';\nimport { LocationFieldEntry } from '../location/LocationField';\nimport { NumberFieldEntry } from '../number/NumberField';\nimport { RangeFieldEntry } from '../range/RangeField';\nimport { RegionFieldEntry } from '../region/RegionField';\nimport { RelationFieldEntry } from '../relation/RelationField';\nimport { RepeaterFieldEntry } from '../repeater/RepeaterField';\nimport { SelectFieldEntry } from '../select/SelectField';\nimport { SlugFieldEntry } from '../slug/SlugField';\nimport { TagsFieldEntry } from '../tags/TagsField';\nimport { TelFieldEntry } from '../tel/TelField';\nimport { TextFieldEntry } from '../text/TextField';\nimport { TextAreaFieldEntry } from '../textarea/TextAreaField';\nimport { TimeFieldEntry } from '../time/TimeField';\nimport { UrlFieldEntry } from '../url/UrlField';\nimport type { FieldEntry } from './types';\n\n/**\n * The entries of the built-in field types. `richtext` and `media` come with their plugins\n * (`@panneau/editor` and `@panneau/media`): without them, `DefinitionField` renders a placeholder.\n * `file` uploads through the upload source of the fields context, or gives the files themselves.\n * `embed` and `location` use its embed source and its maps; `location` loads Leaflet when shown.\n */\nexport const builtInFields: Readonly<Record<string, FieldEntry>> = {\n text: TextFieldEntry,\n textarea: TextAreaFieldEntry,\n number: NumberFieldEntry,\n boolean: BooleanFieldEntry,\n date: DateFieldEntry,\n datetime: DateTimeFieldEntry,\n time: TimeFieldEntry,\n select: SelectFieldEntry,\n email: EmailFieldEntry,\n url: UrlFieldEntry,\n color: ColorFieldEntry,\n slug: SlugFieldEntry,\n file: FileFieldEntry,\n relation: RelationFieldEntry,\n group: GroupFieldEntry,\n repeater: RepeaterFieldEntry,\n tel: TelFieldEntry,\n range: RangeFieldEntry,\n duration: DurationFieldEntry,\n json: JsonFieldEntry,\n tags: TagsFieldEntry,\n embed: EmbedFieldEntry,\n location: LocationFieldEntry,\n country: CountryFieldEntry,\n region: RegionFieldEntry,\n};\n\n/**\n * The built-in fields as a `@panneau/core` plugin: their entries, and the French messages of\n * every Panneau package (`@panneau/ui`, `@panneau/fields`, `@panneau/forms`…, from\n * `@panneau/intl`). Pass it before the plugins that override a type.\n */\nexport const fieldsPlugin: {\n id: string;\n fields: Readonly<Record<string, FieldEntry>>;\n locales: Readonly<Record<string, Record<string, string>>>;\n} = {\n id: 'panneau-fields',\n fields: builtInFields,\n locales: { fr },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,IAAa2B,gBAAsD;CAC/DG,MAAMR;CACNS,UAAUR;CACVS,QAAQnB;CACRoB,SAAShC;CACTiC,MAAM9B;CACN+B,UAAU9B;CACV+B,MAAMZ;CACNa,QAAQnB;CACRoB,OAAO/B;CACPgC,KAAKd;CACLe,OAAOtC;CACPuC,MAAMtB;CACNuB,MAAMjC;CACNkC,UAAU3B;CACV4B,OAAOlC;CACPmC,UAAU5B;CACV6B,KAAKzB;CACL0B,OAAOjC;CACPkC,UAAU1C;CACV2C,MAAMtC;CACNuC,MAAM9B;CACN+B,OAAO3C;CACP4C,UAAUxC;CACVyC,SAASlD;CACTmD,QAAQvC;AACZ;;;;;;AAOA,IAAawC,eAIT;CACAC,IAAI;CACJC,QAAQ9B;CACR+B,SAAS,EAAE1D,GAAG;AAClB"}
1
+ {"version":3,"file":"builtIn.js","names":["fr","AddressFieldEntry","BooleanFieldEntry","ColorFieldEntry","CountryFieldEntry","DateFieldEntry","DateRangeFieldEntry","DateTimeFieldEntry","DurationFieldEntry","EmailFieldEntry","EmbedFieldEntry","FileFieldEntry","GroupFieldEntry","JsonFieldEntry","LinkFieldEntry","LocationFieldEntry","MoneyFieldEntry","NumberFieldEntry","RangeFieldEntry","RegionFieldEntry","RelationFieldEntry","RepeaterFieldEntry","SelectFieldEntry","SlugFieldEntry","TagsFieldEntry","TelFieldEntry","TextFieldEntry","TextAreaFieldEntry","TimeFieldEntry","UrlFieldEntry","FieldEntry","builtInFields","Readonly","Record","text","textarea","number","boolean","date","datetime","time","select","email","url","color","slug","file","relation","group","repeater","tel","range","duration","json","tags","embed","location","country","region","address","link","daterange","money","fieldsPlugin","id","fields","locales"],"sources":["../../src/shared/builtIn.ts"],"sourcesContent":["import { fr } from '@panneau/intl';\n\nimport { AddressFieldEntry } from '../address/AddressField';\nimport { BooleanFieldEntry } from '../boolean/BooleanField';\nimport { ColorFieldEntry } from '../color/ColorField';\nimport { CountryFieldEntry } from '../country/CountryField';\nimport { DateFieldEntry } from '../date/DateField';\nimport { DateRangeFieldEntry } from '../daterange/DateRangeField';\nimport { DateTimeFieldEntry } from '../datetime/DateTimeField';\nimport { DurationFieldEntry } from '../duration/DurationField';\nimport { EmailFieldEntry } from '../email/EmailField';\nimport { EmbedFieldEntry } from '../embed/EmbedField';\nimport { FileFieldEntry } from '../file/FileField';\nimport { GroupFieldEntry } from '../group/GroupField';\nimport { JsonFieldEntry } from '../json/JsonField';\nimport { LinkFieldEntry } from '../link/LinkField';\nimport { LocationFieldEntry } from '../location/LocationField';\nimport { MoneyFieldEntry } from '../money/MoneyField';\nimport { NumberFieldEntry } from '../number/NumberField';\nimport { RangeFieldEntry } from '../range/RangeField';\nimport { RegionFieldEntry } from '../region/RegionField';\nimport { RelationFieldEntry } from '../relation/RelationField';\nimport { RepeaterFieldEntry } from '../repeater/RepeaterField';\nimport { SelectFieldEntry } from '../select/SelectField';\nimport { SlugFieldEntry } from '../slug/SlugField';\nimport { TagsFieldEntry } from '../tags/TagsField';\nimport { TelFieldEntry } from '../tel/TelField';\nimport { TextFieldEntry } from '../text/TextField';\nimport { TextAreaFieldEntry } from '../textarea/TextAreaField';\nimport { TimeFieldEntry } from '../time/TimeField';\nimport { UrlFieldEntry } from '../url/UrlField';\nimport type { FieldEntry } from './types';\n\n/**\n * The entries of the built-in field types. `richtext` and `media` come with their plugins\n * (`@panneau/editor` and `@panneau/media`): without them, `DefinitionField` renders a placeholder.\n * `file` uploads through the upload source of the fields context, or gives the files themselves.\n * `embed`, `location` and `address` use its embed source and its maps; `location` loads Leaflet\n * when shown. `link` searches its pages with the relation source, and picks its files with the\n * `media` entry.\n */\nexport const builtInFields: Readonly<Record<string, FieldEntry>> = {\n text: TextFieldEntry,\n textarea: TextAreaFieldEntry,\n number: NumberFieldEntry,\n boolean: BooleanFieldEntry,\n date: DateFieldEntry,\n datetime: DateTimeFieldEntry,\n time: TimeFieldEntry,\n select: SelectFieldEntry,\n email: EmailFieldEntry,\n url: UrlFieldEntry,\n color: ColorFieldEntry,\n slug: SlugFieldEntry,\n file: FileFieldEntry,\n relation: RelationFieldEntry,\n group: GroupFieldEntry,\n repeater: RepeaterFieldEntry,\n tel: TelFieldEntry,\n range: RangeFieldEntry,\n duration: DurationFieldEntry,\n json: JsonFieldEntry,\n tags: TagsFieldEntry,\n embed: EmbedFieldEntry,\n location: LocationFieldEntry,\n country: CountryFieldEntry,\n region: RegionFieldEntry,\n address: AddressFieldEntry,\n link: LinkFieldEntry,\n daterange: DateRangeFieldEntry,\n money: MoneyFieldEntry,\n};\n\n/**\n * The built-in fields as a `@panneau/core` plugin: their entries, and the French messages of\n * every Panneau package (`@panneau/ui`, `@panneau/fields`, `@panneau/forms`…, from\n * `@panneau/intl`). Pass it before the plugins that override a type.\n */\nexport const fieldsPlugin: {\n id: string;\n fields: Readonly<Record<string, FieldEntry>>;\n locales: Readonly<Record<string, Record<string, string>>>;\n} = {\n id: 'panneau-fields',\n fields: builtInFields,\n locales: { fr },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,IAAa+B,gBAAsD;CAC/DG,MAAMR;CACNS,UAAUR;CACVS,QAAQnB;CACRoB,SAASnC;CACToC,MAAMjC;CACNkC,UAAUhC;CACViC,MAAMZ;CACNa,QAAQnB;CACRoB,OAAOjC;CACPkC,KAAKd;CACLe,OAAOzC;CACP0C,MAAMtB;CACNuB,MAAMnC;CACNoC,UAAU3B;CACV4B,OAAOpC;CACPqC,UAAU5B;CACV6B,KAAKzB;CACL0B,OAAOjC;CACPkC,UAAU5C;CACV6C,MAAMxC;CACNyC,MAAM9B;CACN+B,OAAO7C;CACP8C,UAAUzC;CACV0C,SAASrD;CACTsD,QAAQvC;CACRwC,SAAS1D;CACT2D,MAAM9C;CACN+C,WAAWvD;CACXwD,OAAO9C;AACX;;;;;;AAOA,IAAa+C,eAIT;CACAC,IAAI;CACJC,QAAQlC;CACRmC,SAAS,EAAElE,GAAG;AAClB"}
@@ -1,7 +1,7 @@
1
1
  import { getLocalTimeZone, parseAbsolute, parseDate, parseDateTime, parseTime } from "@internationalized/date";
2
2
  //#region src/shared/dates.ts
3
3
  /** `2026-10-15`, or the date of a date-time. */
4
- function toCalendarDate(value) {
4
+ function toCalendarDate$1(value) {
5
5
  const match = value?.match(/^(\d{4}-\d{2}-\d{2})/);
6
6
  if (match?.[1] === void 0) return null;
7
7
  try {
@@ -44,6 +44,6 @@ function fromTime(value, withSeconds = false) {
44
44
  return withSeconds ? `${time}:${pad(value.second)}` : time;
45
45
  }
46
46
  //#endregion
47
- export { fromDateTime, fromTime, toCalendarDate, toDateTime, toTime };
47
+ export { fromDateTime, fromTime, toCalendarDate$1 as toCalendarDate, toDateTime, toTime };
48
48
 
49
49
  //# sourceMappingURL=dates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dates.js","names":["CalendarDate","CalendarDateTime","Time","ZonedDateTime","getLocalTimeZone","parseAbsolute","parseDate","parseDateTime","parseTime","toCalendarDate","value","match","undefined","OFFSET","toDateTime","timeZone","trim","iso","replace","test","fromDateTime","toAbsoluteString","toString","toTime","length","fromTime","Pick","withSeconds","pad","part","String","padStart","time","hour","minute","second"],"sources":["../../src/shared/dates.ts"],"sourcesContent":["import {\n type CalendarDate,\n type CalendarDateTime,\n type Time,\n type ZonedDateTime,\n getLocalTimeZone,\n parseAbsolute,\n parseDate,\n parseDateTime,\n parseTime,\n} from '@internationalized/date';\n\n/** `2026-10-15`, or the date of a date-time. */\nexport function toCalendarDate(value: string | null | undefined): CalendarDate | null {\n const match = value?.match(/^(\\d{4}-\\d{2}-\\d{2})/);\n if (match?.[1] === undefined) {\n return null;\n }\n try {\n return parseDate(match[1]);\n } catch {\n return null;\n }\n}\n\nconst OFFSET = /(?:Z|[+-]\\d{2}:?\\d{2})$/i;\n\n/**\n * A date-time: with an offset or `Z` (`2026-10-15T13:30:00Z`), in the given time zone; without one\n * (`2026-10-15 09:30:00`), as is.\n */\nexport function toDateTime(\n value: string | null | undefined,\n timeZone: string = getLocalTimeZone(),\n): ZonedDateTime | CalendarDateTime | null {\n if (value === null || value === undefined || value.trim() === '') {\n return null;\n }\n const iso = value.trim().replace(' ', 'T');\n try {\n return OFFSET.test(iso) ? parseAbsolute(iso, timeZone) : parseDateTime(iso);\n } catch {\n return null;\n }\n}\n\n/** Writes a date-time: in UTC (`…Z`) when it has a time zone, without an offset otherwise. */\nexport function fromDateTime(value: ZonedDateTime | CalendarDateTime): string {\n return 'timeZone' in value\n ? value.toAbsoluteString().replace(/\\.000Z$/, 'Z')\n : value.toString();\n}\n\n/** `09:30` or `09:30:15`. */\nexport function toTime(value: string | null | undefined): Time | null {\n if (value === null || value === undefined || !/^\\d{1,2}:\\d{2}(:\\d{2})?/.test(value)) {\n return null;\n }\n try {\n return parseTime(value.length < 5 ? `0${value}` : value);\n } catch {\n return null;\n }\n}\n\n/** Writes a time as `HH:mm`, or `HH:mm:ss` with seconds. */\nexport function fromTime(\n value: Pick<Time, 'hour' | 'minute' | 'second'>,\n withSeconds = false,\n): string {\n const pad = (part: number) => String(part).padStart(2, '0');\n const time = `${pad(value.hour)}:${pad(value.minute)}`;\n return withSeconds ? `${time}:${pad(value.second)}` : time;\n}\n"],"mappings":";;;AAaA,SAAgBS,eAAeC,OAAuD;CAClF,MAAMC,QAAQD,OAAOC,MAAM,sBAAsB;CACjD,IAAIA,QAAQ,OAAOC,KAAAA,GACf,OAAO;CAEX,IAAI;EACA,OAAON,UAAUK,MAAM,EAAE;CAC7B,QAAQ;EACJ,OAAO;CACX;AACJ;AAEA,IAAME,SAAS;;;;;AAMf,SAAgBC,WACZJ,OACAK,WAAmBX,iBAAiB,GACG;CACvC,IAAIM,UAAU,QAAQA,UAAUE,KAAAA,KAAaF,MAAMM,KAAK,MAAM,IAC1D,OAAO;CAEX,MAAMC,MAAMP,MAAMM,KAAK,CAAC,CAACE,QAAQ,KAAK,GAAG;CACzC,IAAI;EACA,OAAOL,OAAOM,KAAKF,GAAG,IAAIZ,cAAcY,KAAKF,QAAQ,IAAIR,cAAcU,GAAG;CAC9E,QAAQ;EACJ,OAAO;CACX;AACJ;;AAGA,SAAgBG,aAAaV,OAAiD;CAC1E,OAAO,cAAcA,QACfA,MAAMW,iBAAiB,CAAC,CAACH,QAAQ,WAAW,GAAG,IAC/CR,MAAMY,SAAS;AACzB;;AAGA,SAAgBC,OAAOb,OAA+C;CAClE,IAAIA,UAAU,QAAQA,UAAUE,KAAAA,KAAa,CAAC,0BAA0BO,KAAKT,KAAK,GAC9E,OAAO;CAEX,IAAI;EACA,OAAOF,UAAUE,MAAMc,SAAS,IAAI,IAAId,UAAUA,KAAK;CAC3D,QAAQ;EACJ,OAAO;CACX;AACJ;;AAGA,SAAgBe,SACZf,OACAiB,cAAc,OACR;CACN,MAAMC,OAAOC,SAAiBC,OAAOD,IAAI,CAAC,CAACE,SAAS,GAAG,GAAG;CAC1D,MAAMC,OAAO,GAAGJ,IAAIlB,MAAMuB,IAAI,EAAC,GAAIL,IAAIlB,MAAMwB,MAAM;CACnD,OAAOP,cAAc,GAAGK,KAAI,GAAIJ,IAAIlB,MAAMyB,MAAM,MAAMH;AAC1D"}
1
+ {"version":3,"file":"dates.js","names":["CalendarDate","CalendarDateTime","Time","ZonedDateTime","getLocalTimeZone","parseAbsolute","parseDate","parseDateTime","parseTime","toCalendarDate","value","match","undefined","OFFSET","toDateTime","timeZone","trim","iso","replace","test","fromDateTime","toAbsoluteString","toString","toTime","length","fromTime","Pick","withSeconds","pad","part","String","padStart","time","hour","minute","second","toCalendarDate"],"sources":["../../src/shared/dates.ts"],"sourcesContent":["import {\n type CalendarDate,\n type CalendarDateTime,\n type Time,\n type ZonedDateTime,\n getLocalTimeZone,\n parseAbsolute,\n parseDate,\n parseDateTime,\n parseTime,\n} from '@internationalized/date';\n\n/** `2026-10-15`, or the date of a date-time. */\nexport function toCalendarDate(value: string | null | undefined): CalendarDate | null {\n const match = value?.match(/^(\\d{4}-\\d{2}-\\d{2})/);\n if (match?.[1] === undefined) {\n return null;\n }\n try {\n return parseDate(match[1]);\n } catch {\n return null;\n }\n}\n\nconst OFFSET = /(?:Z|[+-]\\d{2}:?\\d{2})$/i;\n\n/**\n * A date-time: with an offset or `Z` (`2026-10-15T13:30:00Z`), in the given time zone; without one\n * (`2026-10-15 09:30:00`), as is.\n */\nexport function toDateTime(\n value: string | null | undefined,\n timeZone: string = getLocalTimeZone(),\n): ZonedDateTime | CalendarDateTime | null {\n if (value === null || value === undefined || value.trim() === '') {\n return null;\n }\n const iso = value.trim().replace(' ', 'T');\n try {\n return OFFSET.test(iso) ? parseAbsolute(iso, timeZone) : parseDateTime(iso);\n } catch {\n return null;\n }\n}\n\n/** Writes a date-time: in UTC (`…Z`) when it has a time zone, without an offset otherwise. */\nexport function fromDateTime(value: ZonedDateTime | CalendarDateTime): string {\n return 'timeZone' in value\n ? value.toAbsoluteString().replace(/\\.000Z$/, 'Z')\n : value.toString();\n}\n\n/** `09:30` or `09:30:15`. */\nexport function toTime(value: string | null | undefined): Time | null {\n if (value === null || value === undefined || !/^\\d{1,2}:\\d{2}(:\\d{2})?/.test(value)) {\n return null;\n }\n try {\n return parseTime(value.length < 5 ? `0${value}` : value);\n } catch {\n return null;\n }\n}\n\n/** Writes a time as `HH:mm`, or `HH:mm:ss` with seconds. */\nexport function fromTime(\n value: Pick<Time, 'hour' | 'minute' | 'second'>,\n withSeconds = false,\n): string {\n const pad = (part: number) => String(part).padStart(2, '0');\n const time = `${pad(value.hour)}:${pad(value.minute)}`;\n return withSeconds ? `${time}:${pad(value.second)}` : time;\n}\n"],"mappings":";;;AAaA,SAAgBS,iBAAeC,OAAuD;CAClF,MAAMC,QAAQD,OAAOC,MAAM,sBAAsB;CACjD,IAAIA,QAAQ,OAAOC,KAAAA,GACf,OAAO;CAEX,IAAI;EACA,OAAON,UAAUK,MAAM,EAAE;CAC7B,QAAQ;EACJ,OAAO;CACX;AACJ;AAEA,IAAME,SAAS;;;;;AAMf,SAAgBC,WACZJ,OACAK,WAAmBX,iBAAiB,GACG;CACvC,IAAIM,UAAU,QAAQA,UAAUE,KAAAA,KAAaF,MAAMM,KAAK,MAAM,IAC1D,OAAO;CAEX,MAAMC,MAAMP,MAAMM,KAAK,CAAC,CAACE,QAAQ,KAAK,GAAG;CACzC,IAAI;EACA,OAAOL,OAAOM,KAAKF,GAAG,IAAIZ,cAAcY,KAAKF,QAAQ,IAAIR,cAAcU,GAAG;CAC9E,QAAQ;EACJ,OAAO;CACX;AACJ;;AAGA,SAAgBG,aAAaV,OAAiD;CAC1E,OAAO,cAAcA,QACfA,MAAMW,iBAAiB,CAAC,CAACH,QAAQ,WAAW,GAAG,IAC/CR,MAAMY,SAAS;AACzB;;AAGA,SAAgBC,OAAOb,OAA+C;CAClE,IAAIA,UAAU,QAAQA,UAAUE,KAAAA,KAAa,CAAC,0BAA0BO,KAAKT,KAAK,GAC9E,OAAO;CAEX,IAAI;EACA,OAAOF,UAAUE,MAAMc,SAAS,IAAI,IAAId,UAAUA,KAAK;CAC3D,QAAQ;EACJ,OAAO;CACX;AACJ;;AAGA,SAAgBe,SACZf,OACAiB,cAAc,OACR;CACN,MAAMC,OAAOC,SAAiBC,OAAOD,IAAI,CAAC,CAACE,SAAS,GAAG,GAAG;CAC1D,MAAMC,OAAO,GAAGJ,IAAIlB,MAAMuB,IAAI,EAAC,GAAIL,IAAIlB,MAAMwB,MAAM;CACnD,OAAOP,cAAc,GAAGK,KAAI,GAAIJ,IAAIlB,MAAMyB,MAAM,MAAMH;AAC1D"}
@@ -1 +1 @@
1
- {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/shared/flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAyB/C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CASjD"}
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/shared/flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AA0B/C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CASjD"}
@@ -8,6 +8,7 @@ var COMPACT_TYPES = /* @__PURE__ */ new Set([
8
8
  "tel",
9
9
  "country",
10
10
  "region",
11
+ "money",
11
12
  "number",
12
13
  "date",
13
14
  "datetime",
@@ -1 +1 @@
1
- {"version":3,"file":"flow.js","names":["Field","getSetting","isString","COMPACT_TYPES","Set","isWideField","field","localized","multiple","widget","type","undefined","has"],"sources":["../../src/shared/flow.ts"],"sourcesContent":["import type { Field } from '@panneau/protocol';\n\nimport { getSetting, isString } from './entry';\n\n/** Types whose input is short: they share a row with others in a flow of fields. */\nconst COMPACT_TYPES = new Set([\n 'text',\n 'email',\n 'url',\n 'tel',\n 'country',\n 'region',\n 'number',\n 'date',\n 'datetime',\n 'time',\n 'duration',\n 'color',\n 'select',\n 'boolean',\n 'range',\n 'slug',\n 'relation',\n]);\n\n/**\n * Whether a field takes a whole row where fields flow in columns, such as in a form without a\n * layout or in a group: long inputs (a text area, rich text, blocks), several values, a value per\n * locale, and the types of plugins. Short inputs share a row.\n */\nexport function isWideField(field: Field): boolean {\n if (field.localized === true || field.multiple === true) {\n return true;\n }\n const widget = getSetting(field, 'widget', isString);\n if (field.type === 'select' && widget !== undefined && widget !== 'dropdown') {\n return true;\n }\n return !COMPACT_TYPES.has(field.type);\n}\n"],"mappings":";;;AAKA,IAAMG,gCAAgB,IAAIC,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAAU,CACb;;;;;;AAOD,SAAgBC,YAAYC,OAAuB;CAC/C,IAAIA,MAAMC,cAAc,QAAQD,MAAME,aAAa,MAC/C,OAAO;CAEX,MAAMC,SAASR,WAAWK,OAAO,UAAUJ,QAAQ;CACnD,IAAII,MAAMI,SAAS,YAAYD,WAAWE,KAAAA,KAAaF,WAAW,YAC9D,OAAO;CAEX,OAAO,CAACN,cAAcS,IAAIN,MAAMI,IAAI;AACxC"}
1
+ {"version":3,"file":"flow.js","names":["Field","getSetting","isString","COMPACT_TYPES","Set","isWideField","field","localized","multiple","widget","type","undefined","has"],"sources":["../../src/shared/flow.ts"],"sourcesContent":["import type { Field } from '@panneau/protocol';\n\nimport { getSetting, isString } from './entry';\n\n/** Types whose input is short: they share a row with others in a flow of fields. */\nconst COMPACT_TYPES = new Set([\n 'text',\n 'email',\n 'url',\n 'tel',\n 'country',\n 'region',\n 'money',\n 'number',\n 'date',\n 'datetime',\n 'time',\n 'duration',\n 'color',\n 'select',\n 'boolean',\n 'range',\n 'slug',\n 'relation',\n]);\n\n/**\n * Whether a field takes a whole row where fields flow in columns, such as in a form without a\n * layout or in a group: long inputs (a text area, rich text, blocks), several values, a value per\n * locale, and the types of plugins. Short inputs share a row.\n */\nexport function isWideField(field: Field): boolean {\n if (field.localized === true || field.multiple === true) {\n return true;\n }\n const widget = getSetting(field, 'widget', isString);\n if (field.type === 'select' && widget !== undefined && widget !== 'dropdown') {\n return true;\n }\n return !COMPACT_TYPES.has(field.type);\n}\n"],"mappings":";;;AAKA,IAAMG,gCAAgB,IAAIC,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAAU,CACb;;;;;;AAOD,SAAgBC,YAAYC,OAAuB;CAC/C,IAAIA,MAAMC,cAAc,QAAQD,MAAME,aAAa,MAC/C,OAAO;CAEX,MAAMC,SAASR,WAAWK,OAAO,UAAUJ,QAAQ;CACnD,IAAII,MAAMI,SAAS,YAAYD,WAAWE,KAAAA,KAAaF,WAAW,YAC9D,OAAO;CAEX,OAAO,CAACN,cAAcS,IAAIN,MAAMI,IAAI;AACxC"}
@@ -0,0 +1,26 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { Field } from '@panneau/protocol';
3
+ /** What a part of a value gets from the binding of the fields context: its errors and its blur. */
4
+ export interface BoundPartProps {
5
+ errors?: readonly string[];
6
+ onBlur?: () => void;
7
+ }
8
+ export interface PartBindingProps {
9
+ /** The part, as a field of the definition: the binding reads its errors by its path. */
10
+ field: Field;
11
+ /** Dot path of the part (`address.postalCode`). */
12
+ path: string;
13
+ /** Errors of the part without a binding. */
14
+ errors?: readonly string[];
15
+ /** Blur of the part without a binding. */
16
+ onBlur?: () => void;
17
+ render: (bound: BoundPartProps) => ReactNode;
18
+ }
19
+ /**
20
+ * A part of a value that a field edits itself (the postal code of an address, the URL of a link):
21
+ * the field keeps its whole value, and the binding of the fields context gives each part the
22
+ * errors of its own path, and marks it touched when it loses focus. Without a binding, the part
23
+ * gets `errors` and `onBlur`.
24
+ */
25
+ export declare function BoundPart({ field, path, errors, onBlur, render }: PartBindingProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
26
+ //# sourceMappingURL=part.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"part.d.ts","sourceRoot":"","sources":["../../src/shared/part.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI/C,mGAAmG;AACnG,MAAM,WAAW,cAAc;IAC3B,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC7B,wFAAwF;IACxF,KAAK,EAAE,KAAK,CAAC;IACb,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,SAAS,CAAC;CAChD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,gBAAgB,+TAqBlF"}