@cosmicdrift/kumiko-renderer-web 0.197.0 → 0.197.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-renderer-web",
3
- "version": "0.197.0",
3
+ "version": "0.197.1",
4
4
  "description": "Web-platform bindings for @cosmicdrift/kumiko-renderer. HTML default-primitives, browser history-based navigation, EventSource-backed live events, and a one-call createKumikoApp that mounts the whole stack via react-dom.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -16,9 +16,9 @@
16
16
  "./styles.css": "./src/styles.css"
17
17
  },
18
18
  "dependencies": {
19
- "@cosmicdrift/kumiko-dispatcher-live": "0.197.0",
20
- "@cosmicdrift/kumiko-headless": "0.197.0",
21
- "@cosmicdrift/kumiko-renderer": "0.197.0",
19
+ "@cosmicdrift/kumiko-dispatcher-live": "0.197.1",
20
+ "@cosmicdrift/kumiko-headless": "0.197.1",
21
+ "@cosmicdrift/kumiko-renderer": "0.197.1",
22
22
  "@radix-ui/react-dialog": "^1.1.15",
23
23
  "@radix-ui/react-dropdown-menu": "^2.1.16",
24
24
  "@radix-ui/react-label": "^2.1.8",
@@ -85,6 +85,44 @@ describe("Form = eine Card, Sections als innere Abschnitte", () => {
85
85
  expect(form.className).toContain("gap-4");
86
86
  });
87
87
 
88
+ test("BareFormProvider: sections get the divider rule between them", () => {
89
+ render(
90
+ <BareFormProvider>
91
+ <Form onSubmit={() => {}} testId="bare-sections">
92
+ <Section testId="s1">
93
+ <div>a</div>
94
+ </Section>
95
+ <Section testId="s2">
96
+ <div>b</div>
97
+ </Section>
98
+ </Form>
99
+ </BareFormProvider>,
100
+ );
101
+ const form = screen.getByTestId("bare-sections");
102
+ // jsdom doesn't run Tailwind's JIT, so `:not(:first-child)` can't be
103
+ // asserted via computed style — check the structural precondition the
104
+ // selector relies on (both sections are direct <form> children, in
105
+ // order) plus the divider utility class carrying it.
106
+ const sectionChildren = Array.from(form.children).filter((el) => el.tagName === "SECTION");
107
+ expect(sectionChildren.length).toBe(2);
108
+ expect(sectionChildren[0]).toBe(screen.getByTestId("s1"));
109
+ expect(sectionChildren[1]).toBe(screen.getByTestId("s2"));
110
+ expect(form.className).toContain("[&>section:not(:first-child)]:border-t");
111
+ });
112
+
113
+ test("BareFormProvider: flat AuthCard-shaped fields render no <section> — the divider rule stays inert", () => {
114
+ render(
115
+ <BareFormProvider>
116
+ <Form onSubmit={() => {}} testId="bare-flat">
117
+ <div>field one</div>
118
+ <div>field two</div>
119
+ </Form>
120
+ </BareFormProvider>,
121
+ );
122
+ const form = screen.getByTestId("bare-flat");
123
+ expect(form.querySelectorAll("section").length).toBe(0);
124
+ });
125
+
88
126
  test("Section standalone (außerhalb Form) bleibt eine eigene Card", () => {
89
127
  render(
90
128
  <Section testId="solo" title="Solo">
@@ -98,6 +98,33 @@ describe("RenderEdit", () => {
98
98
  expect(screen.queryByTestId("field-notes")).toBeNull();
99
99
  });
100
100
 
101
+ // A hidden field must not leave an empty grid cell behind — the cell count
102
+ // has to track the visible field count exactly, in both directions.
103
+ test("a hidden field claims no grid cell; toggling visibility adds/removes exactly one cell", () => {
104
+ render(
105
+ <DispatcherProvider dispatcher={makeDispatcher()}>
106
+ <RenderEdit<TestValues>
107
+ screen={makeScreen()}
108
+ entity={orderEntity}
109
+ featureName="orders"
110
+ initial={{ title: "", count: 0, isUrgent: false }}
111
+ writeCommand="order:create"
112
+ />
113
+ </DispatcherProvider>,
114
+ );
115
+
116
+ const grid = screen.getByTestId("section-Basics").querySelector(".grid");
117
+ expect(grid).toBeTruthy();
118
+ // notes is hidden (isUrgent=false): title, count, isUrgent → 3 cells.
119
+ expect(grid?.children.length).toBe(3);
120
+
121
+ const urgentCheckbox = screen.getByTestId("field-isUrgent").querySelector('[role="checkbox"]');
122
+ fireEvent.click(urgentCheckbox as HTMLElement);
123
+
124
+ // notes becomes visible → 4 cells, no leftover empty cell from before.
125
+ expect(grid?.children.length).toBe(4);
126
+ });
127
+
101
128
  // Issue #1677: a section's optional `description` renders as the
102
129
  // Section's subtitle slot underneath the block heading, and a field's
103
130
  // `icon` reaches the DOM as a prefix icon on its input.
@@ -1596,7 +1596,12 @@ function DefaultForm({
1596
1596
  onSubmit(e);
1597
1597
  }}
1598
1598
  data-testid={testId}
1599
- className="flex flex-col gap-4"
1599
+ className={cn(
1600
+ "flex flex-col gap-4",
1601
+ // Bare forms stack sections without a card; without a divider a
1602
+ // section boundary reads as a layout gap, not structure.
1603
+ "[&>section:not(:first-child)]:border-t",
1604
+ )}
1600
1605
  >
1601
1606
  <InsideFormContext.Provider value={true}>{children}</InsideFormContext.Provider>
1602
1607
  {actions !== undefined && (