xmlui 0.7.17 → 0.7.18

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 (41) hide show
  1. package/dist/{apiInterceptorWorker-DkEyFV8g.mjs → apiInterceptorWorker-CXfI_qcP.mjs} +1 -1
  2. package/dist/{grammar.tmLanguage-Qpdanc5_.mjs → grammar.tmLanguage-69iP6c5d.mjs} +23 -9
  3. package/dist/{index-BiwoF6JS.mjs → index-B6CaX0jY.mjs} +10377 -12573
  4. package/dist/scripts/package.json +1 -1
  5. package/dist/scripts/src/components/AppHeader/AppHeader.js +2 -2
  6. package/dist/scripts/src/components/AppState/AppState.js +4 -0
  7. package/dist/scripts/src/components/Carousel/Carousel.js +7 -4
  8. package/dist/scripts/src/components/Carousel/CarouselContext.js +48 -0
  9. package/dist/scripts/src/components/Carousel/CarouselItem.js +1 -4
  10. package/dist/scripts/src/components/Carousel/CarouselItemNative.js +18 -8
  11. package/dist/scripts/src/components/Carousel/CarouselNative.js +20 -11
  12. package/dist/scripts/src/components/ComponentProvider.js +0 -4
  13. package/dist/scripts/src/components/Markdown/Markdown.js +11 -2
  14. package/dist/scripts/src/components/NumberBox/NumberBoxNative.js +1 -1
  15. package/dist/scripts/src/components/{slot-helpers.js → SlotItem.js} +9 -0
  16. package/dist/scripts/src/components/Tabs/TabContext.js +5 -1
  17. package/dist/scripts/src/components/Tabs/TabItem.js +1 -1
  18. package/dist/scripts/src/components/Tabs/TabItemNative.js +11 -5
  19. package/dist/scripts/src/components/Tabs/TabsNative.js +21 -10
  20. package/dist/scripts/src/components/Text/Text.js +3 -2
  21. package/dist/scripts/src/components/Text/TextNative.js +4 -84
  22. package/dist/scripts/src/components/TextBox/TextBoxNative.js +1 -4
  23. package/dist/scripts/src/components/Toggle/Toggle.js +2 -3
  24. package/dist/scripts/src/components/abstractions.js +158 -19
  25. package/dist/scripts/src/components-core/ComponentBed.js +83 -78
  26. package/dist/scripts/src/components-core/CompoundComponent.js +2 -1
  27. package/dist/scripts/src/components-core/appContext/misc-utils.js +1 -0
  28. package/dist/scripts/src/components-core/container/Container.js +43 -21
  29. package/dist/scripts/src/components-core/event-handlers.js +43 -0
  30. package/dist/scripts/src/components-core/utils/misc.js +7 -0
  31. package/dist/scripts/src/parsers/xmlui-parser/ParserError.js +39 -41
  32. package/dist/scripts/src/parsers/xmlui-parser/transform.js +42 -20
  33. package/dist/scripts/src/syntax/grammar.tmLanguage.json +17 -11
  34. package/dist/xmlui-metadata.mjs +2032 -1956
  35. package/dist/xmlui-metadata.umd.js +16 -16
  36. package/dist/xmlui-standalone.umd.js +149 -149
  37. package/dist/xmlui.d.ts +3 -2
  38. package/dist/xmlui.mjs +1 -1
  39. package/package.json +1 -1
  40. package/dist/scripts/src/components/Animation/Animation.js +0 -59
  41. package/dist/scripts/src/components/Animation/AnimationNative.js +0 -75
@@ -76,7 +76,6 @@ exports.Toggle = (0, react_1.forwardRef)(function Toggle({ id, initialValue = fa
76
76
  }, [indeterminate]);
77
77
  const focus = (0, react_1.useCallback)(() => {
78
78
  var _a;
79
- console.log("kakakaka", innerRef.current);
80
79
  (_a = innerRef.current) === null || _a === void 0 ? void 0 : _a.focus();
81
80
  }, []);
82
81
  const setValue = (0, misc_1.useEvent)((newValue) => {
@@ -88,11 +87,11 @@ exports.Toggle = (0, react_1.forwardRef)(function Toggle({ id, initialValue = fa
88
87
  setValue,
89
88
  });
90
89
  }, [focus, registerComponentApi, setValue]);
91
- return ((0, jsx_runtime_1.jsx)(ItemWithLabel_1.ItemWithLabel, { ref: forwardedRef, id: id, label: label, style: style, labelPosition: labelPosition, labelWidth: labelWidth, labelBreak: labelBreak, required: required, enabled: enabled, shrinkToLabel: true, labelStyle: { pointerEvents: readOnly ? "none" : undefined }, children: (0, jsx_runtime_1.jsx)("input", { ref: innerRef, type: "checkbox", role: variant, checked: value, disabled: !enabled, readOnly: readOnly, "aria-readonly": readOnly, onChange: onInputChange, onFocus: handleOnFocus, onBlur: handleOnBlur, className: (0, classnames_1.default)(Toggle_module_scss_1.default.resetAppearance, className, {
90
+ return ((0, jsx_runtime_1.jsx)(ItemWithLabel_1.ItemWithLabel, { ref: forwardedRef, id: id, label: label, style: style, labelPosition: labelPosition, labelWidth: labelWidth, labelBreak: labelBreak, required: required, enabled: enabled, shrinkToLabel: true, labelStyle: { pointerEvents: readOnly ? "none" : undefined }, children: (0, jsx_runtime_1.jsx)("input", { ref: innerRef, type: "checkbox", role: variant, checked: value, disabled: !enabled, required: required, readOnly: readOnly, "aria-readonly": readOnly, "aria-checked": value, onChange: onInputChange, onFocus: handleOnFocus, onBlur: handleOnBlur, className: (0, classnames_1.default)(Toggle_module_scss_1.default.resetAppearance, className, {
92
91
  [Toggle_module_scss_1.default.checkbox]: variant === "checkbox",
93
92
  [Toggle_module_scss_1.default.switch]: variant === "switch",
94
93
  [Toggle_module_scss_1.default.error]: validationStatus === "error",
95
94
  [Toggle_module_scss_1.default.warning]: validationStatus === "warning",
96
95
  [Toggle_module_scss_1.default.valid]: validationStatus === "valid",
97
- }), "aria-checked": value }) }));
96
+ }) }) }));
98
97
  });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.orderingValues = exports.scrollAnchoringNames = exports.scrollAnchoringValues = exports.validationStatusMd = exports.validationStatusNames = exports.validationStatusValues = exports.triggerPositionNames = exports.labelPositionMd = exports.labelPositionNames = exports.labelPositionValues = exports.placementMd = exports.placementNames = exports.statusColorMd = exports.statusColorNames = exports.iconPositionMd = exports.iconPositionNames = exports.iconPositionValues = exports.orientationOptionMd = exports.orientationOptionNames = exports.alignmentOptionMd = exports.alignmentOptionNames = exports.alignmentOptionValues = exports.buttonAriaNames = exports.buttonVariantMd = exports.buttonVariantNames = exports.defaultButtonType = exports.buttonTypesMd = exports.buttonTypeNames = exports.buttonTypeValues = exports.buttonThemeMd = exports.buttonThemeNames = exports.sizeNames = exports.sizeMd = exports.viewportSizeNames = exports.viewportSizeMd = exports.LinkTargetMd = exports.LinkTargetNames = void 0;
3
+ exports.VariantPropsKeys = exports.variantOptionsMd = exports.TextVariantElement = exports.orderingValues = exports.scrollAnchoringNames = exports.scrollAnchoringValues = exports.validationStatusMd = exports.validationStatusNames = exports.validationStatusValues = exports.triggerPositionNames = exports.labelPositionMd = exports.labelPositionNames = exports.labelPositionValues = exports.placementMd = exports.placementNames = exports.statusColorMd = exports.statusColorNames = exports.iconPositionMd = exports.iconPositionNames = exports.iconPositionValues = exports.orientationOptionMd = exports.orientationOptionNames = exports.alignmentOptionMd = exports.alignmentOptionNames = exports.alignmentOptionValues = exports.buttonAriaNames = exports.buttonVariantMd = exports.buttonVariantNames = exports.defaultButtonType = exports.buttonTypesMd = exports.buttonTypeNames = exports.buttonTypeValues = exports.buttonThemeMd = exports.buttonThemeNames = exports.sizeNames = exports.sizeMd = exports.viewportSizeNames = exports.viewportSizeMd = exports.LinkTargetMd = exports.LinkTargetNames = void 0;
4
4
  exports.LinkTargetNames = ["_self", "_blank", "_parent", "_top"];
5
5
  exports.LinkTargetMd = [
6
6
  {
@@ -18,7 +18,7 @@ exports.LinkTargetMd = [
18
18
  {
19
19
  value: "_top",
20
20
  description: "The topmost browsing context. The link will open in the full body of the window. If no ancestors, behaves as _self.",
21
- }
21
+ },
22
22
  ];
23
23
  // --- Available view sizes
24
24
  exports.viewportSizeMd = [
@@ -54,9 +54,18 @@ exports.buttonThemeMd = [
54
54
  exports.buttonTypeValues = ["button", "submit", "reset"];
55
55
  exports.buttonTypeNames = [...exports.buttonTypeValues];
56
56
  exports.buttonTypesMd = [
57
- { value: "button", description: "Regular behavior that only executes logic if explicitly determined." },
58
- { value: "submit", description: "The button submits the form data to the server. This is the default for buttons in a Form or NativeForm component." },
59
- { value: "reset", description: "Resets all the controls to their initial values. Using it is ill advised for UX reasons." },
57
+ {
58
+ value: "button",
59
+ description: "Regular behavior that only executes logic if explicitly determined.",
60
+ },
61
+ {
62
+ value: "submit",
63
+ description: "The button submits the form data to the server. This is the default for buttons in a Form or NativeForm component.",
64
+ },
65
+ {
66
+ value: "reset",
67
+ description: "Resets all the controls to their initial values. Using it is ill advised for UX reasons.",
68
+ },
60
69
  ];
61
70
  exports.defaultButtonType = "button";
62
71
  // --- Available button variants
@@ -64,8 +73,14 @@ const buttonVariantValues = ["solid", "outlined", "ghost"];
64
73
  exports.buttonVariantNames = [...buttonVariantValues];
65
74
  exports.buttonVariantMd = [
66
75
  { value: "solid", description: "A button with a border and a filled background." },
67
- { value: "outlined", description: "The button is displayed with a border and a transparent background." },
68
- { value: "ghost", description: "A button with no border and fill. Only the label is visible; the background is colored when hovered or clicked." },
76
+ {
77
+ value: "outlined",
78
+ description: "The button is displayed with a border and a transparent background.",
79
+ },
80
+ {
81
+ value: "ghost",
82
+ description: "A button with no border and fill. Only the label is visible; the background is colored when hovered or clicked.",
83
+ },
69
84
  ];
70
85
  // --- Available button aria attributes
71
86
  const buttonAriaValues = ["aria-controls", "aria-expanded", "aria-disabled", "aria-label"];
@@ -75,8 +90,14 @@ exports.alignmentOptionValues = ["start", "center", "end"];
75
90
  exports.alignmentOptionNames = [...exports.alignmentOptionValues];
76
91
  exports.alignmentOptionMd = [
77
92
  { value: "center", description: "Place the content in the middle" },
78
- { value: "start", description: "Justify the content to the left (to the right if in right-to-left)" },
79
- { value: "end", description: "Justify the content to the right (to the left if in right-to-left)" },
93
+ {
94
+ value: "start",
95
+ description: "Justify the content to the left (to the right if in right-to-left)",
96
+ },
97
+ {
98
+ value: "end",
99
+ description: "Justify the content to the right (to the left if in right-to-left)",
100
+ },
80
101
  ];
81
102
  // --- Available orientation options
82
103
  const orientationOptionValues = ["horizontal", "vertical"];
@@ -89,8 +110,14 @@ exports.orientationOptionMd = [
89
110
  exports.iconPositionValues = ["start", "end"];
90
111
  exports.iconPositionNames = [...exports.iconPositionValues];
91
112
  exports.iconPositionMd = [
92
- { value: "start", description: "The icon will appear at the start (left side when the left-to-right direction is set)" },
93
- { value: "end", description: "The icon will appear at the end (right side when the left-to-right direction is set)" },
113
+ {
114
+ value: "start",
115
+ description: "The icon will appear at the start (left side when the left-to-right direction is set)",
116
+ },
117
+ {
118
+ value: "end",
119
+ description: "The icon will appear at the end (right side when the left-to-right direction is set)",
120
+ },
94
121
  ];
95
122
  // --- Available status colors
96
123
  const statusColorValues = [
@@ -107,10 +134,10 @@ exports.statusColorNames = [...statusColorValues];
107
134
  exports.statusColorMd = [
108
135
  { value: "primary", description: "Primary theme color, no default icon" },
109
136
  { value: "secondary", description: "Secondary theme color, no default icon" },
110
- { value: "success", description: "Success theme color, \"success\" icon" },
111
- { value: "danger", description: "Warning theme color, \"warning\" icon" },
112
- { value: "warning", description: "Danger theme color, \"danger\" icon" },
113
- { value: "info", description: "Info theme color, \"info\" icon" },
137
+ { value: "success", description: 'Success theme color, "success" icon' },
138
+ { value: "danger", description: 'Warning theme color, "warning" icon' },
139
+ { value: "warning", description: 'Danger theme color, "danger" icon' },
140
+ { value: "info", description: 'Info theme color, "info" icon' },
114
141
  { value: "light", description: "Light theme color, no default icon" },
115
142
  { value: "dark", description: "Dark theme color, no default icon" },
116
143
  ];
@@ -118,8 +145,14 @@ exports.statusColorMd = [
118
145
  const placementValues = ["start", "end", "top", "bottom"];
119
146
  exports.placementNames = [...placementValues];
120
147
  exports.placementMd = [
121
- { value: "start", description: "The left side of the window (left-to-right) or the right side of the window (right-to-left)" },
122
- { value: "end", description: "The right side of the window (left-to-right) or the left side of the window (right-to-left)" },
148
+ {
149
+ value: "start",
150
+ description: "The left side of the window (left-to-right) or the right side of the window (right-to-left)",
151
+ },
152
+ {
153
+ value: "end",
154
+ description: "The right side of the window (left-to-right) or the left side of the window (right-to-left)",
155
+ },
123
156
  { value: "top", description: "The top of the window" },
124
157
  { value: "bottom", description: "The bottom of the window" },
125
158
  ];
@@ -127,8 +160,14 @@ exports.placementMd = [
127
160
  exports.labelPositionValues = ["top", "start", "end", "bottom"];
128
161
  exports.labelPositionNames = [...exports.labelPositionValues];
129
162
  exports.labelPositionMd = [
130
- { value: "start", description: "The left side of the input (left-to-right) or the right side of the input (right-to-left)" },
131
- { value: "end", description: "The right side of the input (left-to-right) or the left side of the input (right-to-left)" },
163
+ {
164
+ value: "start",
165
+ description: "The left side of the input (left-to-right) or the right side of the input (right-to-left)",
166
+ },
167
+ {
168
+ value: "end",
169
+ description: "The right side of the input (left-to-right) or the left side of the input (right-to-left)",
170
+ },
132
171
  { value: "top", description: "The top of the input" },
133
172
  { value: "bottom", description: "The bottom of the input" },
134
173
  ];
@@ -149,3 +188,103 @@ exports.scrollAnchoringValues = ["top", "bottom"];
149
188
  exports.scrollAnchoringNames = [...exports.scrollAnchoringValues];
150
189
  // --- ordering
151
190
  exports.orderingValues = ["asc", "desc"];
191
+ // --- text variants
192
+ const TextVariantKeys = [
193
+ "abbr", // use <abbr>
194
+ "cite", // use <cite>
195
+ "code", // use <code>
196
+ "codefence", // use uniquely styled <![CDATA[
197
+ "deleted", // use <del>
198
+ "inserted", // use <ins>
199
+ "keyboard", // use <kbd>,
200
+ "marked", // use <mark>
201
+ "sample", // use <samp>
202
+ "sub", // use <sub>
203
+ "sup", // use <sup>
204
+ "var", // use <var>
205
+ "strong", // use <strong> element for content that is of greater importance (used in Markdown)
206
+ "em", // use <em> element changes the meaning of a sentence - as spoken emphasis does (used in Markdown)
207
+ "mono", // use monospace font with <![CDATA[
208
+ "title", // Title text in the particular context
209
+ "subtitle", // Subtitle text in the particular context
210
+ "small", // Small text in the particular context
211
+ "caption", // Caption text in the particular context
212
+ "placeholder", // Placeholder text in the particular context
213
+ "paragraph", // use <p>
214
+ "subheading", // use a H6 with some specific defaults
215
+ "tableheading", // use a H3 with some specific defaults
216
+ "secondary", // use a secondary text style
217
+ ];
218
+ exports.TextVariantElement = {
219
+ abbr: "abbr",
220
+ cite: "cite",
221
+ code: "code",
222
+ codefence: "pre",
223
+ deleted: "del",
224
+ inserted: "ins",
225
+ keyboard: "kbd",
226
+ marked: "mark",
227
+ sample: "samp",
228
+ sub: "sub",
229
+ sup: "sup",
230
+ var: "var",
231
+ mono: "pre",
232
+ strong: "strong",
233
+ em: "em",
234
+ title: "span",
235
+ subtitle: "span",
236
+ small: "span",
237
+ caption: "span",
238
+ placeholder: "span",
239
+ paragraph: "p",
240
+ subheading: "h6",
241
+ tableheading: "h6",
242
+ secondary: "span",
243
+ };
244
+ exports.variantOptionsMd = [
245
+ { value: "abbr", description: "Represents an abbreviation or acronym" },
246
+ { value: "caption", description: "Represents the caption (or title) of a table" },
247
+ { value: "cite", description: "Is used to mark up the title of a cited work" },
248
+ { value: "code", description: "Represents a line of code" },
249
+ {
250
+ value: "codefence",
251
+ description: "Handles the display of code blocks if combined with a `code` variant",
252
+ },
253
+ { value: "deleted", description: "Represents text that has been deleted" },
254
+ { value: "em", description: "Marks text to stress emphasis" },
255
+ {
256
+ value: "inserted",
257
+ description: "Represents a range of text that has been added to a document",
258
+ },
259
+ {
260
+ value: "keyboard",
261
+ description: "Represents a span of text denoting textual user input from a keyboard or voice input",
262
+ },
263
+ {
264
+ value: "marked",
265
+ description: "Represents text which is marked or highlighted for reference or notation",
266
+ },
267
+ { value: "mono", description: "Text using a mono style font family" },
268
+ { value: "paragraph", description: "Represents a paragraph" },
269
+ {
270
+ value: "placeholder",
271
+ description: "Text that is mostly used as the placeholder style in input controls",
272
+ },
273
+ { value: "sample", description: "Represents sample (or quoted) output from a computer program" },
274
+ { value: "secondary", description: "Represents a bit dimmed secondary text" },
275
+ { value: "small", description: "Represents side-comments and small print" },
276
+ { value: "sub", description: "Specifies inline text as subscript" },
277
+ { value: "strong", description: "Contents have strong importance" },
278
+ { value: "subheading", description: "Indicates that the text is the subtitle in a heading" },
279
+ {
280
+ value: "subtitle",
281
+ description: "Indicates that the text is the subtitle of some other content",
282
+ },
283
+ { value: "sup", description: "Specifies inline text as superscript" },
284
+ { value: "tableheading", description: "Indicates that the text is a table heading" },
285
+ { value: "title", description: "Indicates that the text is the title of some other content" },
286
+ { value: "var", description: "Represents the name of a variable in a mathematical expression" },
287
+ ];
288
+ const AbbreviationKeys = ["title"];
289
+ const InsertedKeys = ["cite", "dateTime"];
290
+ exports.VariantPropsKeys = [...AbbreviationKeys, ...InsertedKeys];
@@ -64,36 +64,10 @@ const ApiBoundComponent_1 = require("@components-core/ApiBoundComponent");
64
64
  const hooks_1 = require("./utils/hooks");
65
65
  const containers_1 = require("./abstractions/containers");
66
66
  const InspectorContext_1 = require("@components-core/InspectorContext");
67
- const slot_helpers_1 = require("@components/slot-helpers");
67
+ const SlotItem_1 = require("@components/SlotItem");
68
68
  const descriptorHelper_1 = require("@components-core/descriptorHelper");
69
69
  const style_compiler_1 = require("../parsers/style-parser/style-compiler");
70
- function useEventHandler(eventName, lookupEvent, shouldSkip) {
71
- const onEvent = shouldSkip
72
- ? undefined
73
- : lookupEvent(eventName);
74
- const eventHandler = (0, react_1.useCallback)((event) => {
75
- if (onEvent) {
76
- event.stopPropagation();
77
- onEvent(event);
78
- }
79
- }, [onEvent]);
80
- return !onEvent ? undefined : eventHandler;
81
- }
82
- function useMouseEventHandlers(lookupEvent, shouldSkip) {
83
- const onClick = useEventHandler("click", lookupEvent, shouldSkip);
84
- const onMouseLeave = useEventHandler("mouseLeave", lookupEvent, shouldSkip);
85
- const onMouseEnter = useEventHandler("mouseEnter", lookupEvent, shouldSkip);
86
- const onDoubleClick = useEventHandler("doubleClick", lookupEvent, shouldSkip);
87
- if (shouldSkip) {
88
- return constants_1.EMPTY_OBJECT;
89
- }
90
- return {
91
- onClick,
92
- onMouseLeave,
93
- onMouseEnter,
94
- onDoubleClick,
95
- };
96
- }
70
+ const event_handlers_1 = require("./event-handlers");
97
71
  /**
98
72
  * This component's primary responsibility is to transform a particular component definition
99
73
  * into its React representation using the current rendering context.
@@ -125,7 +99,13 @@ const ComponentBed = (0, react_1.forwardRef)(function ComponentBed(_a, ref) {
125
99
  }, [registerComponentApi, uid]);
126
100
  // --- Obtain a function to update the component state
127
101
  const memoedUpdateState = (0, react_1.useCallback)((componentState) => {
128
- dispatch(componentStateChanged(uid, componentState));
102
+ dispatch({
103
+ type: containers_1.ContainerActionKind.COMPONENT_STATE_CHANGED,
104
+ payload: {
105
+ uid,
106
+ state: componentState,
107
+ },
108
+ });
129
109
  }, [dispatch, uid]);
130
110
  // --- Get the tracked APIs of the compomnent
131
111
  const referenceTrackedApi = (0, hooks_1.useReferenceTrackedApi)(state);
@@ -142,6 +122,24 @@ const ComponentBed = (0, react_1.forwardRef)(function ComponentBed(_a, ref) {
142
122
  const memoedLookupAction = (0, react_1.useCallback)((action, actionOptions) => {
143
123
  return lookupAction(action, uid, actionOptions);
144
124
  }, [lookupAction, uid]);
125
+ // --- Obtain the component renderer and descriptor from the component registry
126
+ // --- Memoizes the renderChild function
127
+ const memoedRenderChild = (0, react_1.useCallback)((children, layoutContext, pRenderContext) => {
128
+ return renderChild(children, layoutContext, pRenderContext || parentRenderContext, uidInfoRef);
129
+ }, [renderChild, parentRenderContext, uidInfoRef]);
130
+ // --- Collect the API-bound properties and events of the component to determine
131
+ // --- if the component should be wrapped in an `ApiBoundComponent`
132
+ const apiBoundProps = (0, react_1.useMemo)(() => getApiBoundItems(safeNode.props, "DataSource", "DataSourceRef"), [safeNode.props]);
133
+ const apiBoundEvents = (0, react_1.useMemo)(() => getApiBoundItems(safeNode.events, "APICall", "FileDownload", "FileUpload"), [safeNode.events]);
134
+ const isApiBound = apiBoundProps.length > 0 || apiBoundEvents.length > 0;
135
+ // --- API-bound components provide helpful behavior out of the box, such as transforming API-bound
136
+ // --- events and properties. This extra functionality is implemented in `ApiBoundComponent`.
137
+ if (isApiBound) {
138
+ return ((0, jsx_runtime_1.jsx)(ApiBoundComponent_1.ApiBoundComponent, { uid: uid, renderChild: memoedRenderChild, node: safeNode, apiBoundEvents: apiBoundEvents, apiBoundProps: apiBoundProps, layoutContextRef: layoutContextRef, parentRendererContext: parentRenderContext }, safeNode.uid));
139
+ }
140
+ // --- Obtain the component renderer and descriptor from the component registry
141
+ const componentRegistry = (0, ComponentRegistryContext_1.useComponentRegistry)();
142
+ const { renderer, descriptor, isCompoundComponent } = componentRegistry.lookupComponentRenderer(safeNode.type) || {};
145
143
  // --- Obtain a function that can lookup an event handler, which is bound to a
146
144
  // --- particular event of this component instance
147
145
  const memoedLookupEventHandler = (0, react_1.useCallback)((eventName, actionOptions) => {
@@ -149,6 +147,8 @@ const ComponentBed = (0, react_1.forwardRef)(function ComponentBed(_a, ref) {
149
147
  const action = ((_a = safeNode.events) === null || _a === void 0 ? void 0 : _a[eventName]) || (actionOptions === null || actionOptions === void 0 ? void 0 : actionOptions.defaultHandler);
150
148
  return lookupAction(action, uid, Object.assign({ eventName }, actionOptions));
151
149
  }, [lookupAction, safeNode.events, uid]);
150
+ // --- Set up the mouse event handlers for the component
151
+ const mouseEventHandlers = (0, event_handlers_1.useMouseEventHandlers)(memoedLookupEventHandler, (descriptor === null || descriptor === void 0 ? void 0 : descriptor.nonVisual) || isApiBound);
152
152
  // --- Use the current theme to obtain resources and collect theme variables
153
153
  const { getResourceUrl, themeVars } = (0, ThemeContext_1.useTheme)();
154
154
  // --- Obtain a function that can extract a resource URL from a logical URL
@@ -156,14 +156,6 @@ const ComponentBed = (0, react_1.forwardRef)(function ComponentBed(_a, ref) {
156
156
  const extractedUrl = valueExtractor(url);
157
157
  return getResourceUrl(extractedUrl);
158
158
  }, [getResourceUrl, valueExtractor]);
159
- // --- Obtain the component renderer and descriptor from the component registry
160
- // --- Memoizes the renderChild function
161
- const memoedRenderChild = (0, react_1.useCallback)((children, layoutContext, pRenderContext) => {
162
- return renderChild(children, layoutContext, pRenderContext || parentRenderContext, uidInfoRef);
163
- }, [renderChild, parentRenderContext, uidInfoRef]);
164
- const apiBoundProps = (0, react_1.useMemo)(() => getApiBoundItems(safeNode.props, "DataSource", "DataSourceRef"), [safeNode.props]);
165
- const apiBoundEvents = (0, react_1.useMemo)(() => getApiBoundItems(safeNode.events, "APICall", "FileDownload", "FileUpload"), [safeNode.events]);
166
- const isApiBound = apiBoundProps.length > 0 || apiBoundEvents.length > 0;
167
159
  // --- Collect and compile the layout property values
168
160
  const { cssProps, nonCssProps } = (0, react_1.useMemo)(() => {
169
161
  const resolvedLayoutProps = {};
@@ -178,14 +170,6 @@ const ComponentBed = (0, react_1.forwardRef)(function ComponentBed(_a, ref) {
178
170
  // --- memoize them using shallow comparison to avoid unnecessary re-renders.
179
171
  const stableLayoutCss = (0, hooks_1.useShallowCompareMemoize)(cssProps);
180
172
  const stableLayoutNonCss = (0, hooks_1.useShallowCompareMemoize)(nonCssProps);
181
- // --- API-bound components provide helpful behavior out of the box, such as transforming API-bound
182
- // --- events and properties. This extra functionality is implemented in `ApiBoundComponent`.
183
- if (isApiBound) {
184
- return ((0, jsx_runtime_1.jsx)(ApiBoundComponent_1.ApiBoundComponent, { uid: uid, renderChild: memoedRenderChild, node: safeNode, apiBoundEvents: apiBoundEvents, apiBoundProps: apiBoundProps, layoutContextRef: layoutContextRef, parentRendererContext: parentRenderContext }, safeNode.uid));
185
- }
186
- const componentRegistry = (0, ComponentRegistryContext_1.useComponentRegistry)();
187
- const { renderer, descriptor, isCompoundComponent } = componentRegistry.lookupComponentRenderer(safeNode.type) || {};
188
- const mouseEventHandlers = useMouseEventHandlers(memoedLookupEventHandler, (descriptor === null || descriptor === void 0 ? void 0 : descriptor.nonVisual) || isApiBound);
189
173
  // --- No special behavior, let's render the component according to its definition.
190
174
  let renderedNode = null;
191
175
  let renderingError = null;
@@ -209,6 +193,8 @@ const ComponentBed = (0, react_1.forwardRef)(function ComponentBed(_a, ref) {
209
193
  uid,
210
194
  };
211
195
  if (safeNode.type === "Slot") {
196
+ // --- Transpose the children from the parent component to the slot in
197
+ // --- the compound component
212
198
  renderedNode = slotRenderer(rendererContext, parentRenderContext);
213
199
  }
214
200
  else {
@@ -252,8 +238,8 @@ const ComponentBed = (0, react_1.forwardRef)(function ComponentBed(_a, ref) {
252
238
  if (renderingError) {
253
239
  return ((0, jsx_runtime_1.jsx)(InvalidComponent_1.default, { errors: [renderingError], node: safeNode, children: renderedNode }));
254
240
  }
255
- // --- If we have a single React node with forwarded reference, let's merge the "rest"
256
- // --- properties with it.
241
+ // --- If we have a single React node with forwarded reference, or mouse events
242
+ // --- let's merge the "rest" properties with it.
257
243
  if ((ref || !(0, lodash_es_1.isEmpty)(mouseEventHandlers)) && renderedNode && react_1.default.isValidElement(renderedNode)) {
258
244
  // --- For radix UI/accessibility, read more here:
259
245
  // --- https://www.radix-ui.com/primitives/docs/guides/composition
@@ -262,35 +248,63 @@ const ComponentBed = (0, react_1.forwardRef)(function ComponentBed(_a, ref) {
262
248
  // --- If the rendering resulted in multiple React nodes, wrap them in a fragment.
263
249
  return react_1.default.isValidElement(renderedNode) ? renderedNode : (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: renderedNode });
264
250
  });
251
+ /**
252
+ * This function renders the content of a slot. If the slot is named, it looks for a template
253
+ * in the parent component to render. If the template is not found, it renders the default content
254
+ * of the slot.
255
+ */
265
256
  function slotRenderer({ node, extractValue, renderChild, lookupAction, layoutContext }, parentRenderContext) {
266
- if (!parentRenderContext) {
267
- return undefined;
257
+ // --- Get the template name from the slot
258
+ const templateName = extractValue.asOptionalString(node.props.name);
259
+ if (templateName && !templateName.endsWith("Template")) {
260
+ return ((0, jsx_runtime_1.jsx)(InvalidComponent_1.default, { node: node, errors: [
261
+ `Slot name '${templateName}' is not valid. ` +
262
+ "A named slot should use a name ending with 'Template'.",
263
+ ] }));
268
264
  }
269
- const templateName = extractValue(node.props.name);
270
- if (templateName === undefined) {
271
- return parentRenderContext.renderChild(parentRenderContext.children, layoutContext);
272
- }
273
- else {
274
- let slotProps;
275
- if (!(0, lodash_es_1.isEmpty)(node.props)) {
276
- slotProps = {};
277
- Object.keys(node.props).forEach((key) => {
278
- if (key !== "name") {
279
- let extractedValue = extractValue(node.props[key], true);
280
- if (extractedValue === null || extractedValue === void 0 ? void 0 : extractedValue._ARROW_EXPR_) {
281
- extractedValue = lookupAction(extractedValue);
282
- }
283
- slotProps[key] = extractedValue;
265
+ let slotProps = null;
266
+ if (!(0, lodash_es_1.isEmpty)(node.props)) {
267
+ slotProps = {};
268
+ Object.keys(node.props).forEach((key) => {
269
+ if (key !== "name") {
270
+ let extractedValue = extractValue(node.props[key], true);
271
+ if (extractedValue === null || extractedValue === void 0 ? void 0 : extractedValue._ARROW_EXPR_) {
272
+ extractedValue = lookupAction(extractedValue);
284
273
  }
285
- });
286
- }
287
- if (parentRenderContext.props[templateName]) {
288
- return ((0, jsx_runtime_1.jsx)(slot_helpers_1.SlotItem, { node: parentRenderContext.props[templateName], renderChild: parentRenderContext.renderChild, slotProps: slotProps, layoutContext: layoutContext }));
274
+ slotProps[key] = extractedValue;
275
+ }
276
+ });
277
+ }
278
+ if (parentRenderContext) {
279
+ // --- We may use a named slot to get the content from the parent
280
+ if (templateName === undefined) {
281
+ // --- The slot is not named
282
+ if (!slotProps) {
283
+ // --- simply render the children from the parent
284
+ return parentRenderContext.renderChild(parentRenderContext.children, layoutContext);
285
+ }
286
+ else {
287
+ // --- The slot has properties; let's render the children with the slot properties
288
+ return ((0, jsx_runtime_1.jsx)(SlotItem_1.SlotItem, { node: parentRenderContext.children, renderChild: parentRenderContext.renderChild, slotProps: slotProps, layoutContext: layoutContext }));
289
+ }
289
290
  }
290
291
  else {
291
- return ((0, jsx_runtime_1.jsx)(slot_helpers_1.SlotItem, { node: node.children, renderChild: renderChild, slotProps: slotProps, layoutContext: layoutContext }));
292
+ // --- We have a named slot with optional other properties; let's collect them
293
+ if (parentRenderContext.props[templateName]) {
294
+ // --- The parent provides a template to put into the slot. Let's use
295
+ // --- the parent's context to render the slot content.
296
+ return ((0, jsx_runtime_1.jsx)(SlotItem_1.SlotItem, { node: parentRenderContext.props[templateName], renderChild: parentRenderContext.renderChild, slotProps: slotProps, layoutContext: layoutContext }));
297
+ }
292
298
  }
293
299
  }
300
+ // --- No parent context, render the default slot content
301
+ if (node.children && node.children.length > 0) {
302
+ // --- The parent does not provide a template for the slot. Let's render
303
+ // --- the slot's default children.
304
+ return ((0, jsx_runtime_1.jsx)(SlotItem_1.SlotItem, { node: node.children, renderChild: renderChild, slotProps: slotProps !== null && slotProps !== void 0 ? slotProps : constants_1.EMPTY_OBJECT, layoutContext: layoutContext }));
305
+ }
306
+ // --- We do not render the named slots with names not ending with "Template"
307
+ return undefined;
294
308
  }
295
309
  /**
296
310
  * This function gets the API-bound component properties. A property is API-bound if its value is a
@@ -313,13 +327,4 @@ function getApiBoundItems(items, ...type) {
313
327
  }
314
328
  return ret;
315
329
  }
316
- function componentStateChanged(uid, state) {
317
- return {
318
- type: containers_1.ContainerActionKind.COMPONENT_STATE_CHANGED,
319
- payload: {
320
- uid,
321
- state,
322
- },
323
- };
324
- }
325
330
  exports.default = ComponentBed;
@@ -121,7 +121,7 @@ exports.CompoundComponent = (0, react_1.forwardRef)(({ node, lookupSyncCallback,
121
121
  });
122
122
  }, [node.props]);
123
123
  const memoedParentRenderContext = (0, react_1.useMemo)(() => {
124
- if ((!node.children || node.children.length === 0) && !hasTemplateProps) {
124
+ if (!hasTemplateProps && (!node.children || node.children.length === 0)) {
125
125
  return undefined;
126
126
  }
127
127
  return {
@@ -141,4 +141,5 @@ exports.CompoundComponent = (0, react_1.forwardRef)(({ node, lookupSyncCallback,
141
141
  }
142
142
  return react_1.default.isValidElement(ret) ? ret : (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: ret });
143
143
  });
144
+ // --- Display a name for the component in developer tools
144
145
  exports.CompoundComponent.displayName = "CompoundComponent";
@@ -9,4 +9,5 @@ exports.miscellaneousUtils = {
9
9
  defaultTo: lodash_es_1.defaultTo,
10
10
  toHashObject: misc_1.toHashObject,
11
11
  findByField: misc_1.findByField,
12
+ distinct: misc_1.distinct
12
13
  };
@@ -463,7 +463,7 @@ const MemoizedContainer = (0, react_1.memo)((0, react_1.forwardRef)(function Con
463
463
  if (wrapWithFragment) {
464
464
  // --- Add the `key` attribute to the child
465
465
  if (react_1.default.isValidElement(renderedChild)) {
466
- // --- React can display this element
466
+ // --- React can display this element
467
467
  rendered = react_1.default.cloneElement(renderedChild, { key });
468
468
  }
469
469
  else {
@@ -476,7 +476,7 @@ const MemoizedContainer = (0, react_1.memo)((0, react_1.forwardRef)(function Con
476
476
  });
477
477
  // --- At this point we have a React node for each child
478
478
  if (renderedChildren.length === 1) {
479
- // --- If we have a single (and valid React element) child, we compose its
479
+ // --- If we have a single (and valid React element) child, we compose its
480
480
  // --- `ref` with the parent's `ref`. This allows the parent to access the child's
481
481
  // --- DOM node. Otherwise, we use the child as is.
482
482
  return ref && renderedChildren[0] && (0, react_1.isValidElement)(renderedChildren[0])
@@ -747,30 +747,13 @@ const ComponentContainer = (0, react_1.memo)((0, react_1.forwardRef)(function Co
747
747
  * nested components recursively.
748
748
  */
749
749
  function renderChild({ node, state, dispatch, appContext, lookupAction, lookupSyncCallback, registerComponentApi, renderChild, stateFieldPartChanged, layoutContext, parentRenderContext, memoedVarsRef, cleanup, uidInfoRef, }) {
750
- var _a, _b;
750
+ var _a, _b, _c;
751
751
  // --- Render only visible components
752
752
  if (!(0, extractParam_1.shouldKeep)(node.when, state, appContext)) {
753
753
  return null;
754
754
  }
755
- // --- There is a special case for rendering text. If we have a Slot with a
756
- // --- single text node child, we want to render that in the context of the
757
- // --- parent component. Otherwise, we would not be able to render this:
758
- //
759
- // <Component name='MyComponent'>
760
- // <Markdown><Slot/></Markdown>
761
- // </Component>
762
- //
763
- // and then
764
- //
765
- // <MyComponent>hey lorem ipsum</MyComponent>
766
- if (node.type === "Slot" && ((_a = parentRenderContext === null || parentRenderContext === void 0 ? void 0 : parentRenderContext.children) === null || _a === void 0 ? void 0 : _a.length) === 1) {
767
- if (parentRenderContext.children[0].type === "TextNodeCData" ||
768
- parentRenderContext.children[0].type === "TextNode") {
769
- return parentRenderContext.renderChild(parentRenderContext.children);
770
- }
771
- }
772
755
  // --- We do not parse text nodes specified with CDATA to avoid whitespace collapsing
773
- const nodeValue = (_b = node.props) === null || _b === void 0 ? void 0 : _b.value;
756
+ const nodeValue = (_a = node.props) === null || _a === void 0 ? void 0 : _a.value;
774
757
  if (node.type === "TextNodeCData") {
775
758
  return nodeValue !== null && nodeValue !== void 0 ? nodeValue : "";
776
759
  }
@@ -778,6 +761,45 @@ function renderChild({ node, state, dispatch, appContext, lookupAction, lookupSy
778
761
  if (node.type === "TextNode") {
779
762
  return (0, extractParam_1.extractParam)(state, nodeValue, appContext, true);
780
763
  }
764
+ // --- Rendering a Slot requires some preparations, as TextNode and
765
+ // --- TextNodeCData are virtual nodes. Also, slots may have default templates
766
+ // --- to render when no slot children are specified. The following section
767
+ // --- handles these cases.
768
+ if (node.type === "Slot") {
769
+ // --- Check for special Slot cases
770
+ let slotChildren;
771
+ const templateName = (_b = node.props) === null || _b === void 0 ? void 0 : _b.name;
772
+ console.log("templateName", templateName);
773
+ if (templateName) {
774
+ // --- Let's check the validity of the slot name
775
+ if (!templateName.endsWith("Template")) {
776
+ throw new Error(`Slot name '${templateName}' is not valid. ` +
777
+ "A named slot should use a name ending with 'Template'.");
778
+ }
779
+ // --- Named slot: use a template property from the parent component
780
+ slotChildren = (_c = parentRenderContext === null || parentRenderContext === void 0 ? void 0 : parentRenderContext.props) === null || _c === void 0 ? void 0 : _c[templateName];
781
+ }
782
+ else {
783
+ // --- Children slot: use the children of the parent component
784
+ slotChildren = parentRenderContext === null || parentRenderContext === void 0 ? void 0 : parentRenderContext.children;
785
+ }
786
+ if (!slotChildren) {
787
+ // --- No children to render, let's try the default slot template (if there is any)
788
+ slotChildren = node.children;
789
+ }
790
+ if (slotChildren) {
791
+ const toRender = Array.isArray(slotChildren) ? slotChildren : [slotChildren];
792
+ // --- Check for the virtual nodes. At this point, parentRendererContext is
793
+ // --- undefined when the parent does not provide slot children. In this case,
794
+ // --- the ComponentBed component will render the default slot template.
795
+ if (toRender.length === 1 && parentRenderContext) {
796
+ if (toRender[0].type === "TextNodeCData" || toRender[0].type === "TextNode") {
797
+ // --- Preserve the text and render it in the parent context
798
+ return parentRenderContext.renderChild(toRender);
799
+ }
800
+ }
801
+ }
802
+ }
781
803
  // --- In other cases, we extract the component ID, and then render the component.
782
804
  // --- A component's ID is generally a string with identifier syntax. However, some
783
805
  // --- internal components have IDs with expressions, so we evaluate them.