@lowdefy/blocks-antd 5.3.0 → 5.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 (97) hide show
  1. package/dist/blocks/AutoComplete/AutoComplete.js +1 -0
  2. package/dist/blocks/AutoComplete/meta.js +2 -1
  3. package/dist/blocks/ButtonSelector/ButtonSelector.js +74 -27
  4. package/dist/blocks/ButtonSelector/meta.js +18 -4
  5. package/dist/blocks/Carousel/meta.js +16 -0
  6. package/dist/blocks/CheckboxSelector/CheckboxSelector.js +46 -14
  7. package/dist/blocks/CheckboxSelector/meta.js +7 -1
  8. package/dist/blocks/CheckboxSwitch/CheckboxSwitch.js +1 -0
  9. package/dist/blocks/CheckboxSwitch/meta.js +4 -1
  10. package/dist/blocks/ColorSelector/ColorSelector.js +1 -0
  11. package/dist/blocks/ColorSelector/meta.js +2 -1
  12. package/dist/blocks/ConfigProvider/ConfigProvider.js +1 -0
  13. package/dist/blocks/ConfigProvider/meta.js +7 -0
  14. package/dist/blocks/ConfirmModal/ConfirmModal.js +2 -2
  15. package/dist/blocks/ConfirmModal/meta.js +2 -4
  16. package/dist/blocks/DateRangeSelector/DateRangeSelector.js +4 -9
  17. package/dist/blocks/DateRangeSelector/meta.js +4 -8
  18. package/dist/blocks/DateSelector/DateSelector.js +4 -3
  19. package/dist/blocks/DateSelector/meta.js +4 -5
  20. package/dist/blocks/DateTimeSelector/DateTimeSelector.js +4 -3
  21. package/dist/blocks/DateTimeSelector/meta.js +4 -5
  22. package/dist/blocks/DropdownMenu/meta.js +46 -6
  23. package/dist/blocks/Label/Label.js +30 -5
  24. package/dist/blocks/Label/meta.js +8 -2
  25. package/dist/blocks/ListSelector/ListSelector.js +384 -0
  26. package/dist/blocks/ListSelector/e2e.js +40 -0
  27. package/dist/blocks/ListSelector/meta.js +215 -0
  28. package/dist/blocks/Menu/Menu.js +26 -80
  29. package/dist/blocks/Menu/meta.js +160 -64
  30. package/dist/blocks/MobileMenu/meta.js +50 -50
  31. package/dist/blocks/Modal/Modal.js +2 -2
  32. package/dist/blocks/Modal/meta.js +2 -4
  33. package/dist/blocks/MonthSelector/MonthSelector.js +4 -3
  34. package/dist/blocks/MonthSelector/meta.js +4 -5
  35. package/dist/blocks/MultipleSelector/MultipleSelector.js +41 -9
  36. package/dist/blocks/MultipleSelector/meta.js +24 -5
  37. package/dist/blocks/NumberInput/NumberInput.js +3 -1
  38. package/dist/blocks/NumberInput/meta.js +3 -3
  39. package/dist/blocks/PageHeaderMenu/PageHeaderMenu.js +10 -2
  40. package/dist/blocks/PageHeaderMenu/meta.js +8 -1
  41. package/dist/blocks/PageSidebarLayout/PageSidebarLayout.js +2 -1
  42. package/dist/blocks/PageSidebarLayout/meta.js +8 -1
  43. package/dist/blocks/PageSiderMenu/PageSiderMenu.js +2 -1
  44. package/dist/blocks/PageSiderMenu/meta.js +8 -1
  45. package/dist/blocks/PasswordInput/PasswordInput.js +1 -0
  46. package/dist/blocks/PasswordInput/meta.js +2 -1
  47. package/dist/blocks/PhoneNumberInput/PhoneNumberInput.js +1 -0
  48. package/dist/blocks/PhoneNumberInput/meta.js +2 -1
  49. package/dist/blocks/RadioSelector/RadioSelector.js +44 -14
  50. package/dist/blocks/RadioSelector/meta.js +7 -1
  51. package/dist/blocks/RatingSlider/meta.js +2 -1
  52. package/dist/blocks/SegmentedSelector/SegmentedSelector.js +10 -4
  53. package/dist/blocks/SegmentedSelector/meta.js +7 -4
  54. package/dist/blocks/Selector/Selector.js +55 -9
  55. package/dist/blocks/Selector/meta.js +24 -5
  56. package/dist/blocks/Slider/Slider.js +1 -0
  57. package/dist/blocks/Slider/meta.js +2 -1
  58. package/dist/blocks/Switch/Switch.js +1 -0
  59. package/dist/blocks/Switch/meta.js +2 -1
  60. package/dist/blocks/Tabs/Tabs.js +30 -43
  61. package/dist/blocks/Tabs/meta.js +8 -10
  62. package/dist/blocks/TextArea/TextArea.js +1 -0
  63. package/dist/blocks/TextArea/meta.js +2 -1
  64. package/dist/blocks/TextInput/TextInput.js +1 -0
  65. package/dist/blocks/TextInput/meta.js +2 -1
  66. package/dist/blocks/TreeInput/TreeInput.js +91 -0
  67. package/dist/blocks/TreeInput/e2e.js +33 -0
  68. package/dist/blocks/TreeInput/meta.js +68 -0
  69. package/dist/blocks/TreeMultipleSelector/TreeMultipleSelector.js +161 -0
  70. package/dist/blocks/TreeMultipleSelector/e2e.js +46 -0
  71. package/dist/blocks/TreeMultipleSelector/meta.js +128 -0
  72. package/dist/blocks/TreeSelector/TreeSelector.js +127 -88
  73. package/dist/blocks/TreeSelector/e2e.js +20 -9
  74. package/dist/blocks/TreeSelector/meta.js +70 -254
  75. package/dist/blocks/WeekSelector/WeekSelector.js +2 -1
  76. package/dist/blocks/WeekSelector/meta.js +3 -3
  77. package/dist/blocks/buildMenuItems.js +89 -26
  78. package/dist/blocks/headerActions.js +87 -3
  79. package/dist/blocks/normalizeItemClassAndStyle.js +77 -0
  80. package/dist/blocks.js +3 -0
  81. package/dist/e2e.js +3 -0
  82. package/dist/getContrastTextColor.js +45 -0
  83. package/dist/getOptionColorStyle.js +36 -0
  84. package/dist/getSelectedIndex.js +42 -0
  85. package/dist/getSelectorOptions.js +67 -0
  86. package/dist/getTreeData.js +94 -0
  87. package/dist/metas.js +3 -0
  88. package/dist/schemas/dataOptions.js +36 -0
  89. package/dist/schemas/index.js +1 -0
  90. package/dist/schemas/label.js +3 -1
  91. package/dist/schemas/labelTooltip.js +44 -0
  92. package/dist/schemas/options.js +7 -3
  93. package/dist/schemas/treeSelectTheme.js +125 -0
  94. package/dist/serializeSelectorValue.js +38 -0
  95. package/dist/useSelectorOptions.js +38 -0
  96. package/dist/useSetData.js +27 -0
  97. package/package.json +9 -7
@@ -0,0 +1,94 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import { get, type } from '@lowdefy/helpers';
16
+ import getSelectorOptions from './getSelectorOptions.js';
17
+ // Sentinel parent id for top-level nodes, used as antd TreeSelect `treeDataSimpleMode.rootPId`.
18
+ export const ROOT_PID = '__lowdefy_tree_root__';
19
+ // Turns the flat selector `entries` (from getSelectorOptions) into antd TreeSelect
20
+ // `treeDataSimpleMode` nodes. Each entry already carries `label` (an html string) + `value`
21
+ // (the stored value) + the spread row fields. The antd node `value` is the entry index string
22
+ // (matching the other selectors and getSelectedIndex), so the structural `primaryKey`/`parentKey`
23
+ // stay independent of the stored value. A `parentKey` that points at no known node falls back to
24
+ // root, so a mis-referenced row stays visible rather than orphaned.
25
+ const getTreeData = ({ entries, properties })=>{
26
+ const { primaryKey, parentKey } = properties;
27
+ const hasStructure = type.isString(primaryKey) && type.isString(parentKey);
28
+ const ids = new Set();
29
+ if (hasStructure) {
30
+ entries.forEach((entry)=>{
31
+ if (type.isObject(entry)) ids.add(get(entry, primaryKey));
32
+ });
33
+ }
34
+ return entries.map((entry, index)=>{
35
+ const isObject = type.isObject(entry);
36
+ const id = hasStructure && isObject ? get(entry, primaryKey) : index;
37
+ let pId = ROOT_PID;
38
+ if (hasStructure && isObject) {
39
+ const rawParent = get(entry, parentKey);
40
+ pId = type.isNone(rawParent) || !ids.has(rawParent) ? ROOT_PID : rawParent;
41
+ }
42
+ return {
43
+ id,
44
+ pId,
45
+ value: `${index}`,
46
+ title: isObject ? entry.label : `${entry}`,
47
+ disabled: isObject ? entry.disabled : undefined,
48
+ selectable: isObject ? entry.selectable : undefined
49
+ };
50
+ });
51
+ };
52
+ export default getTreeData;
53
+ // Builds antd `Tree` (nested) nodes for the inline TreeInput block, plus a flat `entries` list
54
+ // aligned to the node keys (each node `key` is its index in `entries`). Driven by a flat
55
+ // `data`/`options` array using `primaryKey`/`parentKey` to assemble the hierarchy (same model as
56
+ // the dropdowns). `entries[Number(key)].value` is the stored value for a selected node; selection
57
+ // matching reuses getSelectedIndex against `entries`.
58
+ export const getTreeNodes = ({ properties })=>{
59
+ const { primaryKey, parentKey } = properties;
60
+ const entries = getSelectorOptions({
61
+ properties
62
+ });
63
+ const nodes = entries.map((entry, index)=>({
64
+ key: `${index}`,
65
+ title: type.isObject(entry) ? entry.label : `${entry}`,
66
+ disabled: type.isObject(entry) ? entry.disabled : undefined,
67
+ disableCheckbox: type.isObject(entry) ? entry.disableCheckbox : undefined,
68
+ selectable: type.isObject(entry) ? entry.selectable : undefined
69
+ }));
70
+ if (!type.isString(primaryKey) || !type.isString(parentKey)) {
71
+ return {
72
+ treeData: nodes,
73
+ entries
74
+ };
75
+ }
76
+ const byId = {};
77
+ entries.forEach((entry, i)=>{
78
+ if (type.isObject(entry)) byId[get(entry, primaryKey)] = nodes[i];
79
+ });
80
+ const roots = [];
81
+ entries.forEach((entry, i)=>{
82
+ const parent = type.isObject(entry) ? get(entry, parentKey) : null;
83
+ if (!type.isNone(parent) && byId[parent]) {
84
+ byId[parent].children = byId[parent].children ?? [];
85
+ byId[parent].children.push(nodes[i]);
86
+ } else {
87
+ roots.push(nodes[i]);
88
+ }
89
+ });
90
+ return {
91
+ treeData: roots,
92
+ entries
93
+ };
94
+ };
package/dist/metas.js CHANGED
@@ -45,6 +45,7 @@ export { default as Footer } from './blocks/Footer/meta.js';
45
45
  export { default as Header } from './blocks/Header/meta.js';
46
46
  export { default as Label } from './blocks/Label/meta.js';
47
47
  export { default as Layout } from './blocks/Layout/meta.js';
48
+ export { default as ListSelector } from './blocks/ListSelector/meta.js';
48
49
  export { default as Masonry } from './blocks/Masonry/meta.js';
49
50
  export { default as MasonryList } from './blocks/MasonryList/meta.js';
50
51
  export { default as Menu } from './blocks/Menu/meta.js';
@@ -87,6 +88,8 @@ export { default as Title } from './blocks/Title/meta.js';
87
88
  export { default as TitleInput } from './blocks/TitleInput/meta.js';
88
89
  export { default as Tooltip } from './blocks/Tooltip/meta.js';
89
90
  export { default as Tour } from './blocks/Tour/meta.js';
91
+ export { default as TreeInput } from './blocks/TreeInput/meta.js';
92
+ export { default as TreeMultipleSelector } from './blocks/TreeMultipleSelector/meta.js';
90
93
  export { default as TreeSelector } from './blocks/TreeSelector/meta.js';
91
94
  export { default as Watermark } from './blocks/Watermark/meta.js';
92
95
  export { default as WeekSelector } from './blocks/WeekSelector/meta.js';
@@ -0,0 +1,36 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ // Shared properties for the data-driven way of populating a selector, as an alternative to
16
+ // `options` (label/value pairs). See concepts/selectors docs for the two ways to drive a selector.
17
+ export const data = {
18
+ type: 'array',
19
+ description: 'Alternative to `options`: an array of raw rows. Each row is rendered to a label with the `html` template, and `valueKey` selects which field becomes the value. Use this to drive a selector directly from data without building label/value pairs in your request.'
20
+ };
21
+ export const html = {
22
+ type: 'string',
23
+ description: 'Nunjucks template that renders each option label when using `data`. The context exposes `item` (the current row) and `index` (the zero-based row index). Ignored when `options` is used.'
24
+ };
25
+ export const valueKey = {
26
+ type: 'string',
27
+ description: 'Field used as the selected value. With `options` it names the value field (defaults to "value"). With `data` it names the field stored when an option is selected; omit it to store the whole row. Supports dotted paths (e.g. "user.id").'
28
+ };
29
+ export const primaryKey = {
30
+ type: 'string',
31
+ description: 'Field used to match the current value (e.g. set with SetState) back to an option for highlighting. Defaults to `valueKey`. Set this when the stored value is the whole row but a single field (e.g. "id") uniquely identifies it. In the tree selectors it also serves as each node’s id, referenced by `parentKey`. Supports dotted paths.'
32
+ };
33
+ export const parentKey = {
34
+ type: 'string',
35
+ description: 'Tree selectors only: names each row’s parent id. Build a flat `data`/`options` array where each row has a `primaryKey` (its own id) and a `parentKey` whose value equals the parent row’s `primaryKey`. Rows whose `parentKey` is empty or points at no row become tree roots. Supports dotted paths.'
36
+ };
@@ -13,6 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ export { default as breadcrumbList } from './breadcrumbList.js';
16
+ export { data, html, valueKey, primaryKey, parentKey } from './dataOptions.js';
16
17
  export { default as disabledDates } from './disabledDates.js';
17
18
  export { default as icon } from './icon.js';
18
19
  export { default as label } from './label.js';
@@ -12,7 +12,8 @@
12
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
- */ export default {
15
+ */ import tooltip from './labelTooltip.js';
16
+ export default {
16
17
  type: 'object',
17
18
  description: 'Label properties.',
18
19
  additionalProperties: false,
@@ -39,6 +40,7 @@
39
40
  type: 'string',
40
41
  description: 'Label title - supports html.'
41
42
  },
43
+ tooltip,
42
44
  span: {
43
45
  type: 'number',
44
46
  description: 'Label inline span.'
@@ -0,0 +1,44 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ export default {
16
+ description: "Help tooltip shown via an icon beside the label. A string sets the tooltip text (supports html), or an object to also customize the icon and color. Use the block's onTooltipClick event to respond to clicks on the icon.",
17
+ oneOf: [
18
+ {
19
+ type: 'string'
20
+ },
21
+ {
22
+ type: 'object',
23
+ additionalProperties: false,
24
+ properties: {
25
+ title: {
26
+ type: 'string',
27
+ description: 'Tooltip text shown on hover - supports html.'
28
+ },
29
+ icon: {
30
+ type: 'string',
31
+ default: 'AiOutlineQuestionCircle',
32
+ description: 'Name of the icon to show beside the label.'
33
+ },
34
+ color: {
35
+ type: 'string',
36
+ description: 'Color of the tooltip icon.',
37
+ docs: {
38
+ displayType: 'color'
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ]
44
+ };
@@ -41,9 +41,6 @@
41
41
  description: 'Options can either be an array of primitive values, on an array of label, value pairs.',
42
42
  items: {
43
43
  type: 'object',
44
- required: [
45
- 'value'
46
- ],
47
44
  properties: {
48
45
  label: {
49
46
  type: 'string',
@@ -76,6 +73,13 @@
76
73
  docs: {
77
74
  displayType: 'yaml'
78
75
  }
76
+ },
77
+ color: {
78
+ type: 'string',
79
+ description: 'Color applied to this option when it is selected. Falls back to the block-level color when not set.',
80
+ docs: {
81
+ displayType: 'color'
82
+ }
79
83
  }
80
84
  }
81
85
  }
@@ -0,0 +1,125 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ // Antd design-token overrides shared by the TreeSelect-based selectors (TreeSelector,
16
+ // TreeMultipleSelector). Covers both the dropdown tree node tokens and the selector tokens.
17
+ export default {
18
+ type: 'object',
19
+ description: 'Antd design token overrides for this block. See <a href="https://ant.design/components/overview#design-token">antd design tokens</a>.',
20
+ docs: {
21
+ displayType: 'yaml',
22
+ link: 'https://ant.design/components/tree-select#design-token'
23
+ },
24
+ properties: {
25
+ nodeSelectedBg: {
26
+ type: 'string',
27
+ description: 'Background color of selected tree node.'
28
+ },
29
+ nodeHoverBg: {
30
+ type: 'string',
31
+ description: 'Background color of hovered tree node.'
32
+ },
33
+ titleHeight: {
34
+ type: 'number',
35
+ default: 24,
36
+ description: 'Height of tree node title.'
37
+ },
38
+ clearBg: {
39
+ type: 'string',
40
+ description: 'Background color of clear button.'
41
+ },
42
+ selectorBg: {
43
+ type: 'string',
44
+ description: 'Background color of the selector.'
45
+ },
46
+ hoverBorderColor: {
47
+ type: 'string',
48
+ description: 'Border color when hovered.'
49
+ },
50
+ activeBorderColor: {
51
+ type: 'string',
52
+ description: 'Border color when active/focused.'
53
+ },
54
+ activeOutlineColor: {
55
+ type: 'string',
56
+ description: 'Outline color when active/focused.'
57
+ },
58
+ optionSelectedBg: {
59
+ type: 'string',
60
+ description: 'Background of selected option.'
61
+ },
62
+ optionSelectedColor: {
63
+ type: 'string',
64
+ description: 'Text color of selected option.'
65
+ },
66
+ optionSelectedFontWeight: {
67
+ type: 'string',
68
+ description: 'Font weight of selected option.'
69
+ },
70
+ optionActiveBg: {
71
+ type: 'string',
72
+ description: 'Background of active (hovered) option.'
73
+ },
74
+ optionFontSize: {
75
+ type: 'number',
76
+ default: 14,
77
+ description: 'Font size of options.'
78
+ },
79
+ optionHeight: {
80
+ type: 'number',
81
+ default: 32,
82
+ description: 'Height of each option.'
83
+ },
84
+ optionLineHeight: {
85
+ type: 'string',
86
+ description: 'Line height of options.'
87
+ },
88
+ optionPadding: {
89
+ type: 'string',
90
+ description: 'Padding of options.'
91
+ },
92
+ multipleSelectorBgDisabled: {
93
+ type: 'string',
94
+ description: 'Background when disabled in multiple mode.'
95
+ },
96
+ multipleItemBg: {
97
+ type: 'string',
98
+ description: 'Background of tag items in multiple mode.'
99
+ },
100
+ multipleItemBorderColor: {
101
+ type: 'string',
102
+ description: 'Border color of tag items.'
103
+ },
104
+ multipleItemHeight: {
105
+ type: 'number',
106
+ default: 24,
107
+ description: 'Height of tag items.'
108
+ },
109
+ multipleItemHeightSM: {
110
+ type: 'number',
111
+ default: 16,
112
+ description: 'Height of tag items (small).'
113
+ },
114
+ multipleItemHeightLG: {
115
+ type: 'number',
116
+ default: 32,
117
+ description: 'Height of tag items (large).'
118
+ },
119
+ zIndexPopup: {
120
+ type: 'number',
121
+ default: 1050,
122
+ description: 'z-index of the dropdown.'
123
+ }
124
+ }
125
+ };
@@ -0,0 +1,38 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import { serializer } from '@lowdefy/helpers';
16
+ // Stable serialization used to compare selector values by identity — both when matching the
17
+ // current value to an option (getSelectedIndex) and when de-duplicating options
18
+ // (getSelectorOptions). The two must agree, so they share this function.
19
+ //
20
+ // Build-time location markers (`~k`, `~r`, `~l`) record where a value sits in the config, not its
21
+ // identity. The same option value carries a different marker depending on where it appears, and a
22
+ // value arriving from state or a request carries none — so a marker-sensitive compare would wrongly
23
+ // treat equal values as different (e.g. a config-literal option vs the same value pre-populated in
24
+ // state). `skipMarkers` only drops these markers when they are non-enumerable; markers loaded from
25
+ // the built JSON config are enumerable, so we also strip them via the replacer. Type markers
26
+ // (`~d` dates, `~e` errors) are part of the value and must be preserved.
27
+ const locationMarkers = new Set([
28
+ '~k',
29
+ '~r',
30
+ '~l'
31
+ ]);
32
+ const dropMarkers = (key, value)=>locationMarkers.has(key) ? undefined : value;
33
+ const serializeSelectorValue = (value)=>serializer.serializeToString(value, {
34
+ stable: true,
35
+ skipMarkers: true,
36
+ replacer: dropMarkers
37
+ });
38
+ export default serializeSelectorValue;
@@ -0,0 +1,38 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import { useMemo } from 'react';
16
+ import getSelectorOptions from './getSelectorOptions.js';
17
+ import useSetData from './useSetData.js';
18
+ // Builds the normalised selector entries from `options`, or from `data` (which may be supplied
19
+ // imperatively via `setData`). Memoised so a large dataset is mapped once, not on every render —
20
+ // when `data` comes from `setData` the dependencies are stable across unrelated re-renders.
21
+ export default function useSelectorOptions({ properties, methods }) {
22
+ const data = useSetData({
23
+ properties,
24
+ methods
25
+ });
26
+ return useMemo(()=>getSelectorOptions({
27
+ properties: {
28
+ ...properties,
29
+ data
30
+ }
31
+ }), [
32
+ data,
33
+ properties.options,
34
+ properties.valueKey,
35
+ properties.primaryKey,
36
+ properties.html
37
+ ]);
38
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import { useEffect, useState } from 'react';
16
+ // Lets a selector receive its `data` imperatively via a registered `setData` method, called with a
17
+ // CallMethod action (e.g. from a request's onSuccess). The dataset is held in component state, so a
18
+ // large list never passes through block `properties` — avoiding the engine re-parsing and
19
+ // re-serializing every row on each update cycle. Falls back to `properties.data` until `setData`
20
+ // has been called. `setValue` (the React setState updater) is stable, so registering once is safe.
21
+ export default function useSetData({ properties, methods }) {
22
+ const [localData, setLocalData] = useState();
23
+ useEffect(()=>{
24
+ methods.registerMethod('setData', setLocalData);
25
+ }, []);
26
+ return localData === undefined ? properties.data : localData;
27
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/blocks-antd",
3
- "version": "5.3.0",
3
+ "version": "5.4.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Lowdefy Ant Design Blocks",
6
6
  "homepage": "https://lowdefy.com",
@@ -45,12 +45,14 @@
45
45
  ],
46
46
  "dependencies": {
47
47
  "@ant-design/icons": "6.1.0",
48
- "@lowdefy/block-utils": "5.3.0",
49
- "@lowdefy/helpers": "5.3.0",
48
+ "@lowdefy/block-utils": "5.4.0",
49
+ "@lowdefy/helpers": "5.4.0",
50
+ "@lowdefy/nunjucks": "5.4.0",
50
51
  "@rc-component/motion": "1.3.1",
51
52
  "classnames": "2.3.2",
52
53
  "dayjs": "1.11.19",
53
- "minisearch": "7.2.0"
54
+ "minisearch": "7.2.0",
55
+ "react-virtuoso": "4.18.7"
54
56
  },
55
57
  "peerDependencies": {
56
58
  "antd": ">=6",
@@ -58,9 +60,9 @@
58
60
  "react-dom": ">=18"
59
61
  },
60
62
  "devDependencies": {
61
- "@lowdefy/block-dev-e2e": "5.3.0",
62
- "@lowdefy/e2e-utils": "5.3.0",
63
- "@lowdefy/node-utils": "5.3.0",
63
+ "@lowdefy/block-dev-e2e": "5.4.0",
64
+ "@lowdefy/e2e-utils": "5.4.0",
65
+ "@lowdefy/node-utils": "5.4.0",
64
66
  "@playwright/test": "1.50.1",
65
67
  "@swc/cli": "0.8.0",
66
68
  "@swc/core": "1.15.18",