xmlui 0.11.2 → 0.11.4

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 (60) hide show
  1. package/dist/lib/{index-DyhCY6Ga.js → index-Cq0EMm3L.js} +390 -347
  2. package/dist/lib/index.css +1 -1
  3. package/dist/lib/{initMock-DN7MXrdn.js → initMock-DCigV4Zh.js} +1 -1
  4. package/dist/lib/language-server-web-worker.js +1 -1
  5. package/dist/lib/language-server.js +1 -1
  6. package/dist/lib/{metadata-utils-D27cn-XB.js → metadata-utils-BiolWMg9.js} +5 -6
  7. package/dist/lib/{server-common-2DaoOOL5.js → server-common-DyCHOk-z.js} +206 -90
  8. package/dist/lib/testing.js +1 -1
  9. package/dist/lib/{transform-Tooy42EB.js → transform-DHf9tQF7.js} +15 -1
  10. package/dist/lib/vite-xmlui-plugin/index.js +19 -2
  11. package/dist/lib/{xmlui-parser-BZZ430Wm.js → xmlui-parser-CHN3mADy.js} +1 -1
  12. package/dist/lib/xmlui-parser.d.ts +2 -0
  13. package/dist/lib/xmlui-parser.js +2 -2
  14. package/dist/lib/{xmlui-serializer-D9D2mQ8m.js → xmlui-serializer-CYNSHAlP.js} +1 -1
  15. package/dist/lib/xmlui.d.ts +2 -1
  16. package/dist/lib/xmlui.js +3 -3
  17. package/dist/metadata/{collectedComponentMetadata-BNSnCrzh.js → collectedComponentMetadata-CLaDZhmc.js} +401 -343
  18. package/dist/metadata/{initMock-CVnDRyRf.js → initMock-Buqah4JF.js} +1 -1
  19. package/dist/metadata/style.css +1 -1
  20. package/dist/metadata/xmlui-metadata.js +1 -1
  21. package/dist/metadata/xmlui-metadata.umd.cjs +3 -3
  22. package/dist/scripts/package.json +1 -1
  23. package/dist/scripts/src/components/AutoComplete/AutoComplete.spec.js +113 -0
  24. package/dist/scripts/src/components/Charts/BarChart/BarChartNative.js +10 -4
  25. package/dist/scripts/src/components/Charts/LabelList/LabelList.js +2 -2
  26. package/dist/scripts/src/components/Charts/LabelList/LabelListNative.js +2 -2
  27. package/dist/scripts/src/components/Charts/LineChart/LineChartNative.js +1 -1
  28. package/dist/scripts/src/components/Checkbox/Checkbox.js +6 -6
  29. package/dist/scripts/src/components/Checkbox/Checkbox.spec.js +30 -99
  30. package/dist/scripts/src/components/ColorPicker/ColorPicker.spec.js +57 -14
  31. package/dist/scripts/src/components/DateInput/DateInput.spec.js +88 -17
  32. package/dist/scripts/src/components/DatePicker/DatePicker.spec.js +9 -9
  33. package/dist/scripts/src/components/NumberBox/NumberBox.spec.js +111 -86
  34. package/dist/scripts/src/components/RadioGroup/RadioGroup.js +6 -6
  35. package/dist/scripts/src/components/RadioGroup/RadioGroup.spec.js +30 -28
  36. package/dist/scripts/src/components/RadioGroup/RadioItemNative.js +1 -1
  37. package/dist/scripts/src/components/Select/Select.js +1 -1
  38. package/dist/scripts/src/components/Select/Select.spec.js +92 -0
  39. package/dist/scripts/src/components/Slider/Slider.js +5 -5
  40. package/dist/scripts/src/components/Slider/Slider.spec.js +63 -29
  41. package/dist/scripts/src/components/Splitter/Splitter.js +53 -3
  42. package/dist/scripts/src/components/Splitter/Splitter.spec.js +313 -0
  43. package/dist/scripts/src/components/Splitter/SplitterNative.js +48 -22
  44. package/dist/scripts/src/components/Splitter/utils.js +7 -2
  45. package/dist/scripts/src/components/Switch/Switch.js +6 -6
  46. package/dist/scripts/src/components/Switch/Switch.spec.js +44 -46
  47. package/dist/scripts/src/components/Text/Text.js +17 -16
  48. package/dist/scripts/src/components/Text/Text.spec.js +284 -0
  49. package/dist/scripts/src/components/TextArea/TextArea.spec.js +94 -2
  50. package/dist/scripts/src/components/TextBox/TextBox.js +5 -3
  51. package/dist/scripts/src/components/TextBox/TextBox.spec.js +92 -59
  52. package/dist/scripts/src/components/TimeInput/TimeInput.spec.js +101 -25
  53. package/dist/scripts/src/components-core/behaviors/CoreBehaviors.js +5 -4
  54. package/dist/scripts/src/language-server/services/common/syntax-node-utilities.js +23 -31
  55. package/dist/scripts/src/language-server/services/format.js +223 -84
  56. package/dist/scripts/src/parsers/xmlui-parser/parser.js +3 -2
  57. package/dist/scripts/src/parsers/xmlui-parser/syntax-node.js +16 -0
  58. package/dist/standalone/xmlui-standalone.es.d.ts +4 -2
  59. package/dist/standalone/xmlui-standalone.umd.js +36 -36
  60. package/package.json +1 -1
@@ -90,11 +90,11 @@ exports.SliderMd = (0, metadata_helpers_1.createMetadata)({
90
90
  [`boxShadow-thumb-${COMP}--hover`]: "0 0 0 6px rgb(from $color-primary r g b / 0.4)",
91
91
  [`backgroundColor-thumb-${COMP}--active`]: "$color-primary-400",
92
92
  [`boxShadow-thumb-${COMP}--active`]: "0 0 0 6px rgb(from $color-primary r g b / 0.4)",
93
- [`borderRadius-${COMP}-default`]: "$borderRadius",
94
- [`borderColor-${COMP}-default`]: "transparent",
95
- [`borderWidth-${COMP}-default`]: "0",
96
- [`borderStyle-${COMP}-default`]: "solid",
97
- [`boxShadow-${COMP}-default`]: "none",
93
+ [`borderRadius-${COMP}--default`]: "$borderRadius",
94
+ [`borderColor-${COMP}--default`]: "transparent",
95
+ [`borderWidth-${COMP}--default`]: "0",
96
+ [`borderStyle-${COMP}--default`]: "solid",
97
+ [`boxShadow-${COMP}--default`]: "none",
98
98
  light: {
99
99
  [`backgroundColor-track-${COMP}--disabled`]: "$color-surface-300",
100
100
  [`backgroundColor-range-${COMP}--disabled`]: "$color-surface-400",
@@ -531,41 +531,75 @@ fixtures_1.test.describe("Theme Variables", () => {
531
531
  }));
532
532
  });
533
533
  // =============================================================================
534
- // VALIDATION STATUS TESTS
534
+ // VALIDATION TESTS
535
535
  // =============================================================================
536
536
  fixtures_1.test.describe("Validation", () => {
537
- (0, fixtures_1.test)(`validationStatus=error applies correctly`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
538
- yield initTestBed(`<Slider validationStatus="error" />`, {
539
- testThemeVars: {
540
- [`borderColor-Slider-error`]: "rgb(255, 0, 0)",
541
- },
542
- });
543
- const sliderTrack = page.locator("[data-track]");
544
- yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("border-color", "rgb(255, 0, 0)");
545
- }));
546
- // NOTE: warning color is not applied correctly
547
- fixtures_1.test.fixme(`validationStatus=warning applies correctly`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
548
- yield initTestBed(`<Slider validationStatus="warning" />`, {
549
- testThemeVars: {
550
- [`borderColor-Slider-warning`]: "rgb(255, 165, 0)",
551
- },
552
- });
553
- const sliderTrack = page.locator("[data-track]");
554
- yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("border-color", "rgb(218, 127, 0)");
555
- }));
556
- (0, fixtures_1.test)(`validationStatus=valid applies correctly`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
557
- yield initTestBed(`<Slider validationStatus="valid" />`, {
558
- testThemeVars: {
559
- [`borderColor-Slider-success`]: "rgb(0, 255, 0)",
560
- },
561
- });
562
- const sliderTrack = page.locator("[data-track]");
563
- yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("border-color", "rgb(0, 255, 0)");
564
- }));
565
537
  (0, fixtures_1.test)("handles invalid validationStatus gracefully", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
566
538
  yield initTestBed(`<Slider validationStatus="invalid" />`);
567
539
  yield (0, fixtures_1.expect)(page.getByRole("slider")).toBeVisible();
568
540
  }));
541
+ [
542
+ { value: "--default", prop: "" },
543
+ { value: "--warning", prop: 'validationStatus="warning"' },
544
+ { value: "--error", prop: 'validationStatus="error"' },
545
+ { value: "--success", prop: 'validationStatus="valid"' },
546
+ ].forEach((variant) => {
547
+ (0, fixtures_1.test)(`applies correct borderRadius ${variant.value}`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
548
+ yield initTestBed(`<Slider ${variant.prop} />`, {
549
+ testThemeVars: { [`borderRadius-Slider${variant.value}`]: "12px" },
550
+ });
551
+ const sliderTrack = page.locator("[data-track]");
552
+ yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("border-radius", "12px");
553
+ }));
554
+ (0, fixtures_1.test)(`applies correct borderColor ${variant.value}`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
555
+ yield initTestBed(`<Slider ${variant.prop} />`, {
556
+ testThemeVars: { [`borderColor-Slider${variant.value}`]: "rgb(255, 0, 0)" },
557
+ });
558
+ const sliderTrack = page.locator("[data-track]");
559
+ yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("border-color", "rgb(255, 0, 0)");
560
+ }));
561
+ (0, fixtures_1.test)(`applies correct borderWidth ${variant.value}`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
562
+ yield initTestBed(`<Slider testId="test" ${variant.prop} />`, {
563
+ testThemeVars: { [`borderWidth-Slider${variant.value}`]: "1px" },
564
+ });
565
+ const sliderTrack = page.locator("[data-track]");
566
+ yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("border-width", "1px");
567
+ }));
568
+ (0, fixtures_1.test)(`applies correct borderStyle ${variant.value}`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
569
+ yield initTestBed(`<Slider ${variant.prop} />`, {
570
+ testThemeVars: { [`borderStyle-Slider${variant.value}`]: "dashed" },
571
+ });
572
+ const sliderTrack = page.locator("[data-track]");
573
+ yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("border-style", "dashed");
574
+ }));
575
+ (0, fixtures_1.test)(`applies correct boxShadow ${variant.value}`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
576
+ yield initTestBed(`<Slider ${variant.prop} />`, {
577
+ testThemeVars: {
578
+ [`boxShadow-Slider${variant.value}`]: "0 2px 8px rgba(0, 0, 0, 0.1)",
579
+ },
580
+ });
581
+ const sliderTrack = page.locator("[data-track]");
582
+ yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("box-shadow", "rgba(0, 0, 0, 0.1) 0px 2px 8px 0px");
583
+ }));
584
+ (0, fixtures_1.test)(`applies correct borderColor on hover ${variant.value}`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
585
+ yield initTestBed(`<Slider ${variant.prop} />`, {
586
+ testThemeVars: { [`borderColor-Slider${variant.value}--hover`]: "rgb(0, 0, 0)" },
587
+ });
588
+ const sliderTrack = page.locator("[data-track]");
589
+ yield sliderTrack.hover();
590
+ yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("border-color", "rgb(0, 0, 0)");
591
+ }));
592
+ (0, fixtures_1.test)(`applies correct boxShadow on hover ${variant.value}`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
593
+ yield initTestBed(`<Slider ${variant.prop} />`, {
594
+ testThemeVars: {
595
+ [`boxShadow-Slider${variant.value}--hover`]: "0 2px 8px rgba(0, 0, 0, 0.1)",
596
+ },
597
+ });
598
+ const sliderTrack = page.locator("[data-track]");
599
+ yield sliderTrack.hover();
600
+ yield (0, fixtures_1.expect)(sliderTrack).toHaveCSS("box-shadow", "rgba(0, 0, 0, 0.1) 0px 2px 8px 0px");
601
+ }));
602
+ });
569
603
  });
570
604
  // =============================================================================
571
605
  // EDGE CASE TESTS
@@ -1,10 +1,44 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
39
  exports.hSplitterComponentRenderer = exports.vSplitterComponentRenderer = exports.splitterComponentRenderer = exports.VSplitterMd = exports.HSplitterMd = exports.SplitterMd = void 0;
7
40
  const jsx_runtime_1 = require("react/jsx-runtime");
41
+ const react_1 = __importStar(require("react"));
8
42
  const Splitter_module_scss_1 = __importDefault(require("./Splitter.module.scss"));
9
43
  const renderers_1 = require("../../components-core/renderers");
10
44
  const misc_1 = require("../../components-core/utils/misc");
@@ -17,7 +51,10 @@ const baseSplitterMd = (0, metadata_helpers_1.createMetadata)({
17
51
  status: "stable",
18
52
  description: "`Splitter` component divides a container into two resizable sections. These " +
19
53
  "are are identified by their names: primary and secondary. They have a " +
20
- "draggable bar between them.",
54
+ "draggable bar between them. When only a single child is visible (due to " +
55
+ "conditional rendering with `when` attributes), the splitter bar is not " +
56
+ "displayed and the single panel stretches to fill the entire viewport of " +
57
+ "the splitter container.",
21
58
  props: {
22
59
  swapped: {
23
60
  description: `This optional booelan property indicates whether the \`${COMP}\` sections are layed out as ` +
@@ -40,7 +77,8 @@ const baseSplitterMd = (0, metadata_helpers_1.createMetadata)({
40
77
  },
41
78
  maxPrimarySize: {
42
79
  description: `This property sets the maximum size the primary section can have. The unit of the size ` +
43
- `value is in pixels or percentages.`,
80
+ `value is in pixels or percentages. Negative values are supported and calculate from the ` +
81
+ `end of the container (e.g., "-20%" means "80% of container", "-100px" means "container size - 100px").`,
44
82
  valueType: "string",
45
83
  defaultValue: SplitterNative_1.defaultProps.maxPrimarySize,
46
84
  },
@@ -80,7 +118,19 @@ function renderSplitter(_a) {
80
118
  if (!(0, misc_1.isComponentDefChildren)(node.children)) {
81
119
  throw new EngineError_1.NotAComponentDefError();
82
120
  }
83
- return ((0, jsx_runtime_1.jsx)(SplitterNative_1.Splitter, { className: className, swapped: extractValue.asOptionalBoolean((_c = node.props) === null || _c === void 0 ? void 0 : _c.swapped), orientation: orientation, splitterTemplate: renderChild((_d = node.props) === null || _d === void 0 ? void 0 : _d.splitterTemplate), initialPrimarySize: extractValue((_e = node.props) === null || _e === void 0 ? void 0 : _e.initialPrimarySize), minPrimarySize: extractValue((_f = node.props) === null || _f === void 0 ? void 0 : _f.minPrimarySize), maxPrimarySize: extractValue((_g = node.props) === null || _g === void 0 ? void 0 : _g.maxPrimarySize), floating: extractValue.asOptionalBoolean((_h = node.props) === null || _h === void 0 ? void 0 : _h.floating), resize: lookupEventHandler("resize"), children: renderChild(node.children) }));
121
+ // Let XMLUI handle the conditional rendering, then count the non-null results
122
+ const renderedChildren = (0, react_1.useMemo)(() => {
123
+ if (!Array.isArray(node.children)) {
124
+ const rendered = renderChild(node.children);
125
+ return rendered ? [rendered] : [];
126
+ }
127
+ return node.children
128
+ .map((child, index) => renderChild(child))
129
+ .filter(child => child !== null && child !== undefined)
130
+ .map((child, index) => react_1.default.cloneElement(child, { key: index }));
131
+ }, [node.children, renderChild]);
132
+ const visibleChildCount = renderedChildren.length;
133
+ return ((0, jsx_runtime_1.jsx)(SplitterNative_1.Splitter, { className: className, swapped: extractValue.asOptionalBoolean((_c = node.props) === null || _c === void 0 ? void 0 : _c.swapped), orientation: orientation, splitterTemplate: renderChild((_d = node.props) === null || _d === void 0 ? void 0 : _d.splitterTemplate), initialPrimarySize: extractValue((_e = node.props) === null || _e === void 0 ? void 0 : _e.initialPrimarySize), minPrimarySize: extractValue((_f = node.props) === null || _f === void 0 ? void 0 : _f.minPrimarySize), maxPrimarySize: extractValue((_g = node.props) === null || _g === void 0 ? void 0 : _g.maxPrimarySize), floating: extractValue.asOptionalBoolean((_h = node.props) === null || _h === void 0 ? void 0 : _h.floating), resize: lookupEventHandler("resize"), visibleChildCount: visibleChildCount, children: renderedChildren }));
84
134
  }
85
135
  exports.splitterComponentRenderer = (0, renderers_1.createComponentRenderer)(COMP, exports.SplitterMd, ({ node, extractValue, renderChild, className, lookupEventHandler }) => {
86
136
  return renderSplitter({
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const component_test_helpers_1 = require("../../testing/component-test-helpers");
13
13
  const fixtures_1 = require("../../testing/fixtures");
14
+ const utils_1 = require("./utils");
14
15
  // =============================================================================
15
16
  // BASIC FUNCTIONALITY TESTS
16
17
  // =============================================================================
@@ -35,6 +36,203 @@ fixtures_1.test.describe("Basic Functionality", () => {
35
36
  yield (0, fixtures_1.expect)(page.getByTestId("splitter")).toBeVisible();
36
37
  yield (0, fixtures_1.expect)(page.getByTestId("single-child")).toBeVisible();
37
38
  }));
39
+ fixtures_1.test.describe("conditional rendering behavior", () => {
40
+ (0, fixtures_1.test)("hides resizer and stretches single panel when second child has when=false", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
41
+ yield initTestBed(`
42
+ <Splitter height="200px" width="400px" testId="splitter">
43
+ <Stack backgroundColor="lightblue" height="100%" testId="primary">Primary</Stack>
44
+ <Stack when="{false}" backgroundColor="darksalmon" height="100%" testId="secondary">Secondary</Stack>
45
+ </Splitter>
46
+ `);
47
+ // Primary panel should be visible
48
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
49
+ // Secondary panel should not be visible (filtered out by when=false)
50
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).not.toBeVisible();
51
+ // Resizer should not be visible when only one child is rendered
52
+ const resizer = page.locator('[class*="resizer"]');
53
+ const isResizerVisible = yield resizer.isVisible().catch(() => false);
54
+ (0, fixtures_1.expect)(isResizerVisible).toBe(false);
55
+ // Primary panel should stretch to fill the entire splitter container
56
+ const splitter = page.getByTestId("splitter");
57
+ const primary = page.getByTestId("primary");
58
+ const splitterBounds = yield (0, component_test_helpers_1.getBounds)(splitter);
59
+ const primaryBounds = yield (0, component_test_helpers_1.getBounds)(primary);
60
+ // Allow small tolerance for borders/padding
61
+ const tolerance = 5;
62
+ (0, fixtures_1.expect)(Math.abs(primaryBounds.width - splitterBounds.width)).toBeLessThan(tolerance);
63
+ (0, fixtures_1.expect)(Math.abs(primaryBounds.height - splitterBounds.height)).toBeLessThan(tolerance);
64
+ }));
65
+ (0, fixtures_1.test)("hides resizer and stretches single panel when first child has when=false", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
66
+ yield initTestBed(`
67
+ <Splitter height="200px" width="400px" testId="splitter">
68
+ <Stack when="{false}" backgroundColor="lightblue" height="100%" testId="primary">Primary</Stack>
69
+ <Stack backgroundColor="darksalmon" height="100%" testId="secondary">Secondary</Stack>
70
+ </Splitter>
71
+ `);
72
+ // Primary panel should not be visible (filtered out by when=false)
73
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).not.toBeVisible();
74
+ // Secondary panel should be visible
75
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).toBeVisible();
76
+ // Resizer should not be visible when only one child is rendered
77
+ const resizer = page.locator('[class*="resizer"]');
78
+ const isResizerVisible = yield resizer.isVisible().catch(() => false);
79
+ (0, fixtures_1.expect)(isResizerVisible).toBe(false);
80
+ // Secondary panel should stretch to fill the entire splitter container
81
+ const splitter = page.getByTestId("splitter");
82
+ const secondary = page.getByTestId("secondary");
83
+ const splitterBounds = yield (0, component_test_helpers_1.getBounds)(splitter);
84
+ const secondaryBounds = yield (0, component_test_helpers_1.getBounds)(secondary);
85
+ // Allow small tolerance for borders/padding
86
+ const tolerance = 5;
87
+ (0, fixtures_1.expect)(Math.abs(secondaryBounds.width - splitterBounds.width)).toBeLessThan(tolerance);
88
+ (0, fixtures_1.expect)(Math.abs(secondaryBounds.height - splitterBounds.height)).toBeLessThan(tolerance);
89
+ }));
90
+ (0, fixtures_1.test)("shows resizer when both children are visible", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
91
+ yield initTestBed(`
92
+ <Splitter height="200px" width="400px" testId="splitter">
93
+ <Stack backgroundColor="lightblue" height="100%" testId="primary">Primary</Stack>
94
+ <Stack backgroundColor="darksalmon" height="100%" testId="secondary">Secondary</Stack>
95
+ </Splitter>
96
+ `);
97
+ // Both panels should be visible
98
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
99
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).toBeVisible();
100
+ // Resizer should be visible when both children are rendered
101
+ const resizer = page.locator('[class*="resizer"]');
102
+ yield (0, fixtures_1.expect)(resizer).toBeVisible();
103
+ }));
104
+ (0, fixtures_1.test)("dynamically updates when child visibility changes", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
105
+ const { testStateDriver } = yield initTestBed(`
106
+ <Fragment var.showSecondary="{true}">
107
+ <Splitter height="200px" width="400px" testId="splitter">
108
+ <Stack backgroundColor="lightblue" height="100%" testId="primary">Primary</Stack>
109
+ <Stack when="{showSecondary}" backgroundColor="darksalmon" height="100%" testId="secondary">Secondary</Stack>
110
+ </Splitter>
111
+ <Button testId="toggle" onClick="showSecondary = !showSecondary">Toggle Secondary</Button>
112
+ </Fragment>
113
+ `);
114
+ // Initially both panels should be visible
115
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
116
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).toBeVisible();
117
+ // Resizer should be visible
118
+ const resizer = page.locator('[class*="resizer"]');
119
+ yield (0, fixtures_1.expect)(resizer).toBeVisible();
120
+ // Click toggle to hide secondary panel
121
+ yield page.getByTestId("toggle").click();
122
+ // Primary should still be visible, secondary should be hidden
123
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
124
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).not.toBeVisible();
125
+ // Resizer should now be hidden
126
+ const isResizerVisible = yield resizer.isVisible().catch(() => false);
127
+ (0, fixtures_1.expect)(isResizerVisible).toBe(false);
128
+ // Primary panel should stretch to fill container
129
+ const splitter = page.getByTestId("splitter");
130
+ const primary = page.getByTestId("primary");
131
+ const splitterBounds = yield (0, component_test_helpers_1.getBounds)(splitter);
132
+ const primaryBounds = yield (0, component_test_helpers_1.getBounds)(primary);
133
+ const tolerance = 5;
134
+ (0, fixtures_1.expect)(Math.abs(primaryBounds.width - splitterBounds.width)).toBeLessThan(tolerance);
135
+ // Click toggle again to show secondary panel
136
+ yield page.getByTestId("toggle").click();
137
+ // Both panels should be visible again
138
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
139
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).toBeVisible();
140
+ // Resizer should be visible again
141
+ yield (0, fixtures_1.expect)(resizer).toBeVisible();
142
+ }));
143
+ (0, fixtures_1.test)("handles when condition with complex expressions", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
144
+ const { testStateDriver } = yield initTestBed(`
145
+ <Fragment var.count="{0}">
146
+ <Splitter height="200px" width="400px" testId="splitter">
147
+ <Stack backgroundColor="lightblue" height="100%" testId="primary">Primary</Stack>
148
+ <Stack when="{count > 5}" backgroundColor="darksalmon" height="100%" testId="secondary">Secondary</Stack>
149
+ </Splitter>
150
+ <Button testId="increment" onClick="count = count + 1">Increment</Button>
151
+ <Text testId="count-display">{count}</Text>
152
+ </Fragment>
153
+ `);
154
+ // Initially only primary should be visible (count = 0, which is not > 5)
155
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
156
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).not.toBeVisible();
157
+ // Resizer should be hidden
158
+ const resizer = page.locator('[class*="resizer"]');
159
+ const isResizerVisible1 = yield resizer.isVisible().catch(() => false);
160
+ (0, fixtures_1.expect)(isResizerVisible1).toBe(false);
161
+ // Click increment 6 times to make count > 5
162
+ for (let i = 0; i < 6; i++) {
163
+ yield page.getByTestId("increment").click();
164
+ }
165
+ yield (0, fixtures_1.expect)(page.getByTestId("count-display")).toHaveText("6");
166
+ // Now both panels should be visible
167
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
168
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).toBeVisible();
169
+ // Resizer should be visible
170
+ yield (0, fixtures_1.expect)(resizer).toBeVisible();
171
+ }));
172
+ (0, fixtures_1.test)("works with multiple conditionally hidden children", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
173
+ yield initTestBed(`
174
+ <Splitter height="200px" width="400px" testId="splitter">
175
+ <Stack when="{false}" backgroundColor="lightblue" height="100%" testId="child1">Child 1</Stack>
176
+ <Stack when="{false}" backgroundColor="darksalmon" height="100%" testId="child2">Child 2</Stack>
177
+ <Stack backgroundColor="lightgreen" height="100%" testId="child3">Child 3</Stack>
178
+ </Splitter>
179
+ `);
180
+ // Only child3 should be visible
181
+ yield (0, fixtures_1.expect)(page.getByTestId("child1")).not.toBeVisible();
182
+ yield (0, fixtures_1.expect)(page.getByTestId("child2")).not.toBeVisible();
183
+ yield (0, fixtures_1.expect)(page.getByTestId("child3")).toBeVisible();
184
+ // Resizer should be hidden (only one visible child)
185
+ const resizer = page.locator('[class*="resizer"]');
186
+ const isResizerVisible = yield resizer.isVisible().catch(() => false);
187
+ (0, fixtures_1.expect)(isResizerVisible).toBe(false);
188
+ // Child3 should stretch to fill container
189
+ const splitter = page.getByTestId("splitter");
190
+ const child3 = page.getByTestId("child3");
191
+ const splitterBounds = yield (0, component_test_helpers_1.getBounds)(splitter);
192
+ const child3Bounds = yield (0, component_test_helpers_1.getBounds)(child3);
193
+ const tolerance = 5;
194
+ (0, fixtures_1.expect)(Math.abs(child3Bounds.width - splitterBounds.width)).toBeLessThan(tolerance);
195
+ }));
196
+ (0, fixtures_1.test)("handles all children being conditionally hidden", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
197
+ yield initTestBed(`
198
+ <Splitter height="200px" width="400px" testId="splitter">
199
+ <Stack when="{false}" backgroundColor="lightblue" height="100%" testId="child1">Child 1</Stack>
200
+ <Stack when="{false}" backgroundColor="darksalmon" height="100%" testId="child2">Child 2</Stack>
201
+ </Splitter>
202
+ `);
203
+ // No children should be visible
204
+ yield (0, fixtures_1.expect)(page.getByTestId("child1")).not.toBeVisible();
205
+ yield (0, fixtures_1.expect)(page.getByTestId("child2")).not.toBeVisible();
206
+ // Splitter should still be visible but empty
207
+ yield (0, fixtures_1.expect)(page.getByTestId("splitter")).toBeVisible();
208
+ // Resizer should not be visible
209
+ const resizer = page.locator('[class*="resizer"]');
210
+ const isResizerVisible = yield resizer.isVisible().catch(() => false);
211
+ (0, fixtures_1.expect)(isResizerVisible).toBe(false);
212
+ }));
213
+ (0, fixtures_1.test)("works with different orientations", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
214
+ yield initTestBed(`
215
+ <Splitter height="200px" width="400px" orientation="horizontal" testId="splitter">
216
+ <Stack backgroundColor="lightblue" height="100%" testId="primary">Primary</Stack>
217
+ <Stack when="{false}" backgroundColor="darksalmon" height="100%" testId="secondary">Secondary</Stack>
218
+ </Splitter>
219
+ `);
220
+ // Primary should be visible, secondary should not
221
+ yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
222
+ yield (0, fixtures_1.expect)(page.getByTestId("secondary")).not.toBeVisible();
223
+ // Resizer should be hidden
224
+ const resizer = page.locator('[class*="resizer"]');
225
+ const isResizerVisible = yield resizer.isVisible().catch(() => false);
226
+ (0, fixtures_1.expect)(isResizerVisible).toBe(false);
227
+ // Primary should stretch horizontally to fill container
228
+ const splitter = page.getByTestId("splitter");
229
+ const primary = page.getByTestId("primary");
230
+ const splitterBounds = yield (0, component_test_helpers_1.getBounds)(splitter);
231
+ const primaryBounds = yield (0, component_test_helpers_1.getBounds)(primary);
232
+ const tolerance = 5;
233
+ (0, fixtures_1.expect)(Math.abs(primaryBounds.width - splitterBounds.width)).toBeLessThan(tolerance);
234
+ }));
235
+ });
38
236
  fixtures_1.test.describe("orientation property", () => {
39
237
  (0, fixtures_1.test)("orientation='horizontal' arranges sections left to right", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
40
238
  yield initTestBed(`
@@ -282,6 +480,54 @@ fixtures_1.test.describe("Basic Functionality", () => {
282
480
  const bounds = yield (0, component_test_helpers_1.getBounds)(primary);
283
481
  (0, fixtures_1.expect)(bounds.width).toBeLessThanOrEqual(310); // Allow small tolerance
284
482
  }));
483
+ (0, fixtures_1.test)("negative maxPrimarySize in pixels constrains from end", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createSplitterDriver }) {
484
+ yield initTestBed(`
485
+ <Splitter height="200px" width="400px" orientation="horizontal" maxPrimarySize="-100px" testId="splitter">
486
+ <Stack backgroundColor="lightblue" height="100%" testId="primary"/>
487
+ <Stack backgroundColor="darksalmon" height="100%" testId="secondary"/>
488
+ </Splitter>
489
+ `);
490
+ const splitter = page.getByTestId("splitter");
491
+ const primary = page.getByTestId("primary");
492
+ const driver = yield createSplitterDriver(splitter);
493
+ // Try to drag resizer far to the right
494
+ yield driver.dragResizer(350, 0);
495
+ // Primary should not be larger than 400 - 100 = 300px
496
+ const bounds = yield (0, component_test_helpers_1.getBounds)(primary);
497
+ (0, fixtures_1.expect)(bounds.width).toBeLessThanOrEqual(310); // Allow small tolerance for 300px max
498
+ }));
499
+ (0, fixtures_1.test)("negative maxPrimarySize in percentage constrains from end", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createSplitterDriver }) {
500
+ yield initTestBed(`
501
+ <Splitter height="200px" width="400px" orientation="horizontal" maxPrimarySize="-25%" testId="splitter">
502
+ <Stack backgroundColor="lightblue" height="100%" testId="primary"/>
503
+ <Stack backgroundColor="darksalmon" height="100%" testId="secondary"/>
504
+ </Splitter>
505
+ `);
506
+ const splitter = page.getByTestId("splitter");
507
+ const primary = page.getByTestId("primary");
508
+ const driver = yield createSplitterDriver(splitter);
509
+ // Try to drag resizer far to the right
510
+ yield driver.dragResizer(350, 0);
511
+ // Primary should not be larger than 75% of 400px = 300px
512
+ const bounds = yield (0, component_test_helpers_1.getBounds)(primary);
513
+ (0, fixtures_1.expect)(bounds.width).toBeLessThanOrEqual(310); // Allow small tolerance for 300px max
514
+ }));
515
+ (0, fixtures_1.test)("negative maxPrimarySize works in vertical orientation", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createSplitterDriver }) {
516
+ yield initTestBed(`
517
+ <Splitter height="400px" width="200px" orientation="vertical" maxPrimarySize="-100px" testId="splitter">
518
+ <Stack backgroundColor="lightblue" width="100%" testId="primary"/>
519
+ <Stack backgroundColor="darksalmon" width="100%" testId="secondary"/>
520
+ </Splitter>
521
+ `);
522
+ const splitter = page.getByTestId("splitter");
523
+ const primary = page.getByTestId("primary");
524
+ const driver = yield createSplitterDriver(splitter);
525
+ // Try to drag resizer far down
526
+ yield driver.dragResizer(0, 350);
527
+ // Primary should not be larger than 400 - 100 = 300px height
528
+ const bounds = yield (0, component_test_helpers_1.getBounds)(primary);
529
+ (0, fixtures_1.expect)(bounds.height).toBeLessThanOrEqual(310); // Allow small tolerance for 300px max
530
+ }));
285
531
  });
286
532
  fixtures_1.test.describe("resize event", () => {
287
533
  (0, fixtures_1.test)("fires resize event when dragging", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createSplitterDriver }) {
@@ -540,4 +786,71 @@ fixtures_1.test.describe("Other Edge Cases", () => {
540
786
  yield (0, fixtures_1.expect)(page.getByTestId("primary")).toBeVisible();
541
787
  yield (0, fixtures_1.expect)(page.getByTestId("secondary")).toBeVisible();
542
788
  }));
789
+ (0, fixtures_1.test)("conditional rendering works with different child component types", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
790
+ yield initTestBed(`
791
+ <Splitter height="200px" width="400px" testId="splitter">
792
+ <VStack when="{false}" backgroundColor="lightblue" height="100%" testId="vstack">
793
+ <Text>VStack Content</Text>
794
+ </VStack>
795
+ <Text backgroundColor="darksalmon" height="100%" testId="text">Just Text</Text>
796
+ <Fragment when="{false}" testId="fragment">
797
+ <Stack backgroundColor="lightgreen" height="100%">Fragment Content</Stack>
798
+ </Fragment>
799
+ </Splitter>
800
+ `);
801
+ // Only the Text component should be visible
802
+ yield (0, fixtures_1.expect)(page.getByTestId("vstack")).not.toBeVisible();
803
+ yield (0, fixtures_1.expect)(page.getByTestId("text")).toBeVisible();
804
+ yield (0, fixtures_1.expect)(page.getByTestId("fragment")).not.toBeVisible();
805
+ // Resizer should be hidden since only one child is visible
806
+ const resizer = page.locator('[class*="resizer"]');
807
+ const isResizerVisible = yield resizer.isVisible().catch(() => false);
808
+ (0, fixtures_1.expect)(isResizerVisible).toBe(false);
809
+ // Text component should stretch to fill container
810
+ const splitter = page.getByTestId("splitter");
811
+ const text = page.getByTestId("text");
812
+ const splitterBounds = yield (0, component_test_helpers_1.getBounds)(splitter);
813
+ const textBounds = yield (0, component_test_helpers_1.getBounds)(text);
814
+ const tolerance = 5;
815
+ (0, fixtures_1.expect)(Math.abs(textBounds.width - splitterBounds.width)).toBeLessThan(tolerance);
816
+ }));
817
+ });
818
+ // =============================================================================
819
+ // UTILITY FUNCTION TESTS
820
+ // =============================================================================
821
+ fixtures_1.test.describe("Utility Functions", () => {
822
+ fixtures_1.test.describe("parseSize", () => {
823
+ (0, fixtures_1.test)("parses positive pixel values", () => {
824
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("100px", 400)).toBe(100);
825
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("200px", 400)).toBe(200);
826
+ });
827
+ (0, fixtures_1.test)("parses positive percentage values", () => {
828
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("50%", 400)).toBe(200);
829
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("25%", 400)).toBe(100);
830
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("100%", 400)).toBe(400);
831
+ });
832
+ (0, fixtures_1.test)("parses negative pixel values (calculated from end)", () => {
833
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("-100px", 400)).toBe(300); // 400 - 100
834
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("-50px", 400)).toBe(350); // 400 - 50
835
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("-200px", 600)).toBe(400); // 600 - 200
836
+ });
837
+ (0, fixtures_1.test)("parses negative percentage values (calculated from end)", () => {
838
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("-20%", 400)).toBe(320); // 80% of 400
839
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("-50%", 400)).toBe(200); // 50% of 400
840
+ (0, fixtures_1.expect)((0, utils_1.parseSize)("-10%", 600)).toBe(540); // 90% of 600
841
+ });
842
+ (0, fixtures_1.test)("throws error for invalid format", () => {
843
+ (0, fixtures_1.expect)(() => (0, utils_1.parseSize)("100", 400)).toThrow("Invalid size format. Use px or %.");
844
+ (0, fixtures_1.expect)(() => (0, utils_1.parseSize)("100em", 400)).toThrow("Invalid size format. Use px or %.");
845
+ (0, fixtures_1.expect)(() => (0, utils_1.parseSize)("invalid", 400)).toThrow("Invalid size format. Use px or %.");
846
+ });
847
+ });
848
+ fixtures_1.test.describe("toPercentage", () => {
849
+ (0, fixtures_1.test)("converts pixel size to percentage", () => {
850
+ (0, fixtures_1.expect)((0, utils_1.toPercentage)(200, 400)).toBe(50);
851
+ (0, fixtures_1.expect)((0, utils_1.toPercentage)(100, 400)).toBe(25);
852
+ (0, fixtures_1.expect)((0, utils_1.toPercentage)(400, 400)).toBe(100);
853
+ (0, fixtures_1.expect)((0, utils_1.toPercentage)(0, 400)).toBe(0);
854
+ });
855
+ });
543
856
  });