@synerise/ds-condition-blocks 0.1.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 (67) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/CLAUDE.md +202 -0
  3. package/LICENSE.md +21 -0
  4. package/README.md +39 -0
  5. package/dist/components/ConditionAddButton/ConditionAddButton.d.ts +15 -0
  6. package/dist/components/ConditionAddButton/ConditionAddButton.js +17 -0
  7. package/dist/components/ConditionAddButton/ConditionAddButton.styles.d.ts +1 -0
  8. package/dist/components/ConditionAddButton/ConditionAddButton.styles.js +8 -0
  9. package/dist/components/ConditionAddButton/ConditionAddButton.types.d.ts +13 -0
  10. package/dist/components/ConditionAddButton/ConditionAddButton.types.js +1 -0
  11. package/dist/components/ConditionConnector/ConditionConnector.d.ts +14 -0
  12. package/dist/components/ConditionConnector/ConditionConnector.js +13 -0
  13. package/dist/components/ConditionConnector/ConditionConnector.styles.d.ts +14 -0
  14. package/dist/components/ConditionConnector/ConditionConnector.styles.js +25 -0
  15. package/dist/components/ConditionConnector/ConditionConnector.types.d.ts +11 -0
  16. package/dist/components/ConditionConnector/ConditionConnector.types.js +1 -0
  17. package/dist/components/ConditionEntity/ConditionEntity.d.ts +16 -0
  18. package/dist/components/ConditionEntity/ConditionEntity.js +18 -0
  19. package/dist/components/ConditionEntity/ConditionEntity.styles.d.ts +4 -0
  20. package/dist/components/ConditionEntity/ConditionEntity.styles.js +15 -0
  21. package/dist/components/ConditionEntity/ConditionEntity.types.d.ts +12 -0
  22. package/dist/components/ConditionEntity/ConditionEntity.types.js +1 -0
  23. package/dist/components/ConditionGroup/ConditionGroup.d.ts +14 -0
  24. package/dist/components/ConditionGroup/ConditionGroup.js +13 -0
  25. package/dist/components/ConditionGroup/ConditionGroup.styles.d.ts +3 -0
  26. package/dist/components/ConditionGroup/ConditionGroup.styles.js +10 -0
  27. package/dist/components/ConditionGroup/ConditionGroup.types.d.ts +9 -0
  28. package/dist/components/ConditionGroup/ConditionGroup.types.js +1 -0
  29. package/dist/components/ConditionRemove/ConditionRemove.d.ts +17 -0
  30. package/dist/components/ConditionRemove/ConditionRemove.js +24 -0
  31. package/dist/components/ConditionRemove/ConditionRemove.styles.d.ts +5 -0
  32. package/dist/components/ConditionRemove/ConditionRemove.styles.js +16 -0
  33. package/dist/components/ConditionRemove/ConditionRemove.types.d.ts +10 -0
  34. package/dist/components/ConditionRemove/ConditionRemove.types.js +1 -0
  35. package/dist/components/ConditionRow/ConditionRow.d.ts +21 -0
  36. package/dist/components/ConditionRow/ConditionRow.js +24 -0
  37. package/dist/components/ConditionRow/ConditionRow.styles.d.ts +9 -0
  38. package/dist/components/ConditionRow/ConditionRow.styles.js +31 -0
  39. package/dist/components/ConditionRow/ConditionRow.types.d.ts +22 -0
  40. package/dist/components/ConditionRow/ConditionRow.types.js +1 -0
  41. package/dist/components/ConditionRows/ConditionRows.d.ts +13 -0
  42. package/dist/components/ConditionRows/ConditionRows.js +14 -0
  43. package/dist/components/ConditionRows/ConditionRows.styles.d.ts +3 -0
  44. package/dist/components/ConditionRows/ConditionRows.styles.js +10 -0
  45. package/dist/components/ConditionRows/ConditionRows.types.d.ts +13 -0
  46. package/dist/components/ConditionRows/ConditionRows.types.js +1 -0
  47. package/dist/components/ConditionSlot/ConditionSlot.d.ts +26 -0
  48. package/dist/components/ConditionSlot/ConditionSlot.js +22 -0
  49. package/dist/components/ConditionSlot/ConditionSlot.styles.d.ts +10 -0
  50. package/dist/components/ConditionSlot/ConditionSlot.styles.js +41 -0
  51. package/dist/components/ConditionSlot/ConditionSlot.types.d.ts +21 -0
  52. package/dist/components/ConditionSlot/ConditionSlot.types.js +1 -0
  53. package/dist/components/ConditionTextSlot/ConditionTextSlot.d.ts +13 -0
  54. package/dist/components/ConditionTextSlot/ConditionTextSlot.js +12 -0
  55. package/dist/components/ConditionTextSlot/ConditionTextSlot.styles.d.ts +3 -0
  56. package/dist/components/ConditionTextSlot/ConditionTextSlot.styles.js +11 -0
  57. package/dist/components/ConditionTextSlot/ConditionTextSlot.types.d.ts +9 -0
  58. package/dist/components/ConditionTextSlot/ConditionTextSlot.types.js +1 -0
  59. package/dist/constants.d.ts +11 -0
  60. package/dist/constants.js +6 -0
  61. package/dist/errorMessage.styles.d.ts +6 -0
  62. package/dist/errorMessage.styles.js +9 -0
  63. package/dist/index.d.ts +18 -0
  64. package/dist/index.js +20 -0
  65. package/dist/modules.d.js +1 -0
  66. package/dist/modules.d.ts +0 -0
  67. package/package.json +57 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # 0.1.0 (2026-09-22)
7
+
8
+
9
+ ### Features
10
+
11
+ * add @synerise/ds-condition-blocks — building blocks for filtering-condition layouts ([ed332ce](https://github.com/Synerise/synerise-design/commit/ed332cefddd418a293a73c51c57e9a4c1ed4f22f))
package/CLAUDE.md ADDED
@@ -0,0 +1,202 @@
1
+ # ConditionBlocks (`@synerise/ds-condition-blocks`)
2
+
3
+ > Presentational, composable building blocks for filtering-condition layouts — a layout skeleton
4
+ > (group / rows / row / slot / connector) plus leaf primitives (entity / text / add / remove). All
5
+ > state and behaviour live in the consuming app; these blocks carry only the design-system look and
6
+ > ds-condition's grow/shrink-within-bounds sizing.
7
+
8
+ ## Package structure
9
+
10
+ ```
11
+ src/
12
+ index.ts — public barrel (named exports only, no default export)
13
+ constants.ts — CONDITION_REMOVE_CLASS, CONDITION_ROWS_GAP
14
+ errorMessage.styles.ts — shared ErrorMessage = styled(ErrorText) from ds-typography
15
+ components/
16
+ ConditionGroup/ — outer wrapper: entity | rows
17
+ ConditionRows/ — vertical stack of rows + add button
18
+ ConditionRow/ — one horizontal row; renders its own connector + error
19
+ ConditionSlot/ — sizing wrapper for one control (the grow/shrink primitive)
20
+ ConditionConnector/ — tree-line connector cell (::before stub, ::after line)
21
+ ConditionEntity/ — flex wrapper for the entity/context chip(s)
22
+ ConditionTextSlot/ — inline text between controls
23
+ ConditionAddButton/ — "and where" / "Add another" action row
24
+ ConditionRemove/ — hover/focus-revealed ✕ for a row
25
+ __specs__/ConditionBlocks.spec.tsx
26
+ ```
27
+
28
+ ## Public exports
29
+
30
+ All named exports (no default). Each block also re-exports its `*Props` type. Every block is a
31
+ `forwardRef` and forwards native attributes (`data-*` / `aria-*` / `className` / `style`) via
32
+ `WithHTMLAttributes`.
33
+
34
+ ### `ConditionGroup`
35
+ Outermost wrapper — entity on the left, `ConditionRows` on the right. Forward the ref and pass the
36
+ node as `getPopupContainer` to enclosed dropdowns so their popovers share one stacking context.
37
+
38
+ | Prop | Type | Default | Description |
39
+ |------|------|---------|-------------|
40
+ | `children` | `ReactNode` | — | Entity wrapper + `ConditionRows` |
41
+ | `gap` | `number \| string` | `12` | Gap between entity and rows |
42
+
43
+ ### `ConditionRows`
44
+ Vertical container for the rows and the add button; fills the remaining width, stays shrinkable.
45
+
46
+ | Prop | Type | Default | Description |
47
+ |------|------|---------|-------------|
48
+ | `children` | `ReactNode` | — | `ConditionRow`s + `ConditionAddButton` |
49
+ | `gap` | `number \| string` | `16` (`CONDITION_ROWS_GAP`) | Vertical gap between rows |
50
+
51
+ ### `ConditionRow`
52
+ A single horizontal row of slots/text. **Renders its own leading connector** (from `connector`) and
53
+ its own error below the slots; reveals a descendant `ConditionRemove` on hover.
54
+
55
+ | Prop | Type | Default | Description |
56
+ |------|------|---------|-------------|
57
+ | `children` | `ReactNode` | — | The slots / text |
58
+ | `gap` | `number \| string` | `12` | Gap between children |
59
+ | `align` | `'start' \| 'center' \| 'baseline'` | `'start'` | Cross-axis alignment (`center`/`baseline` for text-interleaved rows) |
60
+ | `errorMessage` | `ReactNode` | — | Rendered below the slots, aligned with the first slot |
61
+ | `connector` | `ConditionConnectorProps` | — | When set, renders a leading `ConditionConnector` with these props |
62
+
63
+ ### `ConditionSlot`
64
+ The sizing primitive — wraps one control, controls its grow/shrink within bounds, and cascades
65
+ `min-width: 0`.
66
+
67
+ | Prop | Type | Default | Description |
68
+ |------|------|---------|-------------|
69
+ | `children` | `ReactNode` | — | The control |
70
+ | `variant` | `'rigid' \| 'fill' \| 'shrink'` | `'rigid'` | Preset flex budget (rigid=operator, fill=factor, shrink=parameter) |
71
+ | `grow` | `number` | — | Explicit `flex-grow` (overrides `variant`) |
72
+ | `shrink` | `number` | — | Explicit `flex-shrink` |
73
+ | `basis` | `string` | `'auto'` | Explicit `flex-basis` |
74
+ | `minWidth` | `number \| string` | — | Floor (pair with `shrink`) |
75
+ | `maxWidth` | `number \| string` | — | Cap |
76
+ | `errorMessage` | `ReactNode` | — | Rendered below the control |
77
+
78
+ ### `ConditionConnector`
79
+ The tree-line connector cell. Usually rendered by `ConditionRow` / `ConditionAddButton` via their
80
+ `connector` / `connectorProps`, not composed directly.
81
+
82
+ | Prop | Type | Default | Description |
83
+ |------|------|---------|-------------|
84
+ | `first` | `boolean` | — | First row — full-width horizontal stub |
85
+ | `last` | `boolean` | — | Last row — stops the vertical line at the stub |
86
+ | `readOnly` | `boolean` | — | Hides the trailing line on the last row |
87
+
88
+ ### `ConditionEntity`
89
+ Flex-row wrapper for the entity/context chip(s) at the start of a group (≥1 slot).
90
+
91
+ | Prop | Type | Default | Description |
92
+ |------|------|---------|-------------|
93
+ | `children` | `ReactNode` | — | The chip(s) — a `ds-button` custom-color / `ds-context-selector` |
94
+ | `gap` | `number \| string` | `12` | Gap between multiple slots |
95
+ | `errorMessage` | `ReactNode` | — | Rendered below the entity |
96
+
97
+ ### `ConditionTextSlot`
98
+ Inline, non-interactive text between controls.
99
+
100
+ | Prop | Type | Default | Description |
101
+ |------|------|---------|-------------|
102
+ | `children` | `ReactNode` | — | The label |
103
+ | `muted` | `boolean` | `false` | Lighter secondary colour |
104
+
105
+ ### `ConditionAddButton`
106
+ The add-condition action row; renders the consumer's control and an optional leading connector.
107
+
108
+ | Prop | Type | Default | Description |
109
+ |------|------|---------|-------------|
110
+ | `children` | `ReactNode` | — | The add control (e.g. a ghost `ds-button`) |
111
+ | `withConnector` | `boolean` | `false` | Draw a `ConditionConnector` before the control |
112
+ | `connectorProps` | `Pick<ConditionConnectorProps, 'first' \| 'last' \| 'readOnly'>` | — | Props for that connector |
113
+
114
+ ### `ConditionRemove`
115
+ Hover/focus-revealed ✕ that removes a row. Carries `CONDITION_REMOVE_CLASS` so an enclosing
116
+ `ConditionRow` toggles it via `:hover` / `:focus-within`.
117
+
118
+ | Prop | Type | Default | Description |
119
+ |------|------|---------|-------------|
120
+ | `onClick` | `(event) => void` | — | Remove handler |
121
+ | `revealOnRowHover` | `boolean` | `true` | Hidden until the row is hovered or focused; `false` = always visible |
122
+ | `disabled` | `boolean` | `false` | |
123
+ | `aria-label` | `string` | `DS.CONDITION-BLOCKS.REMOVE` (`'Remove'`) | Accessible label; overrides the translated default |
124
+
125
+ ## Usage pattern
126
+
127
+ ```tsx
128
+ import {
129
+ ConditionGroup,
130
+ ConditionRows,
131
+ ConditionRow,
132
+ ConditionSlot,
133
+ ConditionEntity,
134
+ ConditionAddButton,
135
+ ConditionRemove,
136
+ } from '@synerise/ds-condition-blocks';
137
+
138
+ <ConditionGroup>
139
+ <ConditionEntity>{/* entity chip */}</ConditionEntity>
140
+ <ConditionRows>
141
+ <ConditionRow connector={{ first: true, last: true }} errorMessage={error}>
142
+ <ConditionSlot variant="shrink" minWidth={120}>{/* parameter */}</ConditionSlot>
143
+ <ConditionSlot variant="rigid">{/* operator */}</ConditionSlot>
144
+ <ConditionSlot variant="fill">
145
+ {/* value control — ds-input with autoResize.stretchToFit */}
146
+ <ConditionRemove />
147
+ </ConditionSlot>
148
+ </ConditionRow>
149
+ <ConditionAddButton withConnector>{/* ghost button */}</ConditionAddButton>
150
+ </ConditionRows>
151
+ </ConditionGroup>;
152
+ ```
153
+
154
+ ## Styling
155
+
156
+ Each block has a co-located `*.styles.ts` using `@synerise/ds-core` theme tokens. The shared
157
+ `ErrorMessage` (`errorMessage.styles.ts`) is `styled(ErrorText)` from `@synerise/ds-typography`
158
+ (red-600) with its default bottom margin replaced by an 8px top margin.
159
+
160
+ ## The sizing guarantee (grow/shrink within bounds)
161
+
162
+ 1. **`ConditionSlot` flex budgets** — `rigid` = `flex: 0 0`, `fill` = `flex: 30 1`,
163
+ `shrink` = `flex: 0 400` (+ a `minWidth` floor).
164
+ 2. **A `min-width: 0` cascade** — `ConditionRows` → `ConditionRow` → `ConditionSlot` → `& > *`, so
165
+ children can shrink below their intrinsic width and the row never overflows its parent.
166
+ 3. **A stretch-to-fit input** — the value control the consumer passes (`@synerise/ds-input` with
167
+ `autoResize.stretchToFit`) pins its `max-width` to the measured parent width.
168
+
169
+ Put shrinkable controls inside a `ConditionSlot`, never as a bare child of `ConditionRow`.
170
+
171
+ ## Key dependencies
172
+
173
+ Only what the package actually imports. The controls a consumer places inside the slots
174
+ (`ds-button`, `ds-input`, `ds-tooltip`, `ds-context-selector`, …) are the *consumer's* dependencies,
175
+ not this package's — do not add them here.
176
+
177
+ - `@synerise/ds-icon` — `CloseS` in `ConditionRemove`
178
+ - `@synerise/ds-typography` — `ErrorText` behind the shared error label
179
+ - `@synerise/ds-utils` — `WithHTMLAttributes`, `toCssSize`
180
+ - `react-intl` (peer) — the translated `aria-label` on `ConditionRemove`
181
+
182
+ ## Implementation notes
183
+
184
+ - **`ConditionRow` owns the connector** — pass `connector={{ first, last }}`; do not compose a
185
+ `<ConditionConnector>` child. The row lays out `[connector | content-column]`, where the content
186
+ column holds the slots and the error, so the error aligns with the first slot (not the connector).
187
+ - **The connector line is content-independent** — the connector cell `align-self: stretch`es to the
188
+ row's full height and its `::after` fills the cell + bridges the fixed `CONDITION_ROWS_GAP`, so a
189
+ multi-line or custom `errorMessage` stays connected to the next row (no per-error-height guess).
190
+ - **`ConditionRemove` reveal is CSS-only, and visual only** — the button is hidden with
191
+ `opacity: 0` + `pointer-events: none`, never `visibility`/`display`, so it stays in the
192
+ accessibility tree and the tab order. The enclosing `ConditionRow` reveals it via
193
+ `:hover` **and `:focus-within`**, and the button reveals itself on `:focus-visible` so keyboard
194
+ focus never lands on something invisible. Hiding it with `visibility: hidden` (as an earlier
195
+ revision did) removed it from the focus order entirely and left keyboard and screen-reader users
196
+ unable to remove a row — WCAG 2.1 AA 2.1.1. In tests query it normally
197
+ (`getByRole('button', { name: 'Remove' })`); no `hidden: true` is needed.
198
+ - **`ConditionRemove` carries no margin** — the container owns its spacing. Nested in the last
199
+ `ConditionSlot` (the usual placement) the slot's `SlotContent` offsets it by 8px; placed straight
200
+ in a `ConditionRow` it is spaced by that row's `gap`. A margin on the button itself stacked on top
201
+ of the row gap and left the ✕ too far from its control.
202
+ - No default exports; `src/index.ts` is the only barrel.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Synerise
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # @synerise/ds-condition-blocks
2
+
3
+ Composable, **presentational** building blocks for filtering-condition layouts.
4
+
5
+ Where `@synerise/ds-condition` bakes in one fixed structure (context chip → optional
6
+ aggregate → rows of factor / operator / parameter), these blocks let a consuming app
7
+ compose _any_ condition layout — including free-form, text-interleaved ones — while keeping
8
+ the design-system look and, crucially, ds-condition's **grow/shrink-within-bounds** sizing.
9
+ All state and behaviour (menus, values, add/remove orchestration) live in the consuming app.
10
+
11
+ ## Blocks
12
+
13
+ | Block | Role |
14
+ | --- | --- |
15
+ | `ConditionGroup` | Outermost wrapper — entity on the left, rows on the right. |
16
+ | `ConditionRows` | Vertical stack of rows (and the add button); sets the inter-row gap. |
17
+ | `ConditionRow` | Horizontal flex row; fills its parent but never overflows. Renders its own leading `connector` and an optional `errorMessage`. |
18
+ | `ConditionSlot` | Sizing wrapper for one control (`rigid` / `fill` / `shrink` presets or explicit `grow`/`shrink`/`basis`/`minWidth`/`maxWidth`); optional `errorMessage`. |
19
+ | `ConditionConnector` | The tree-line connector cell (usually rendered via a row's `connector` prop). |
20
+ | `ConditionEntity` | Flex wrapper for the entity/context chip(s); optional `errorMessage`. |
21
+ | `ConditionTextSlot` | Inline label for text-interleaved layouts ("Show only [N] items with the same [x]"). |
22
+ | `ConditionAddButton` | Ghost "and where" / "Add another" / "and then…" action, with an optional connector. |
23
+ | `ConditionRemove` | Hover-revealed ✕ for a row. |
24
+
25
+ ## The sizing guarantee
26
+
27
+ Three mechanisms, ported from `@synerise/ds-condition`, keep controls stretching and
28
+ shrinking within bounds without the row ever overflowing its parent:
29
+
30
+ 1. **`ConditionSlot` flex budgets** — `rigid` = `flex: 0 0`, `fill` = `flex: 30 1`,
31
+ `shrink` = `flex: 0 400`; pair `shrink` with a `minWidth` floor.
32
+ 2. **A `min-width: 0` cascade** — every level (`ConditionRows` → `ConditionRow` → `ConditionSlot`
33
+ → its child) is `min-width: 0`, so children can shrink below their intrinsic width.
34
+ 3. **A stretch-to-fit value input** — the input the consuming app passes (`@synerise/ds-input`
35
+ with `autoResize.stretchToFit`) pins its `max-width` to the measured parent width, so it fills
36
+ the slot but never spills out.
37
+
38
+ Put shrinkable controls in a `ConditionSlot` (never a bare child of `ConditionRow`) so the
39
+ cascade applies.
@@ -0,0 +1,15 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Row that hangs an "add" control off the tree line — the "and where" / "Add another" /
4
+ * "and then…" action. Presentational only: the consuming app passes the actual control (e.g. a
5
+ * ghost `ds-button`) as `children`.
6
+ */
7
+ export declare const ConditionAddButton: React.ForwardRefExoticComponent<{
8
+ children: React.ReactNode;
9
+ withConnector?: boolean;
10
+ connectorProps?: Pick<import('../..').ConditionConnectorProps, "first" | "last" | "readOnly">;
11
+ } & Omit<React.HTMLAttributes<HTMLDivElement>, keyof {
12
+ children: React.ReactNode;
13
+ withConnector?: boolean;
14
+ connectorProps?: Pick<import('../..').ConditionConnectorProps, "first" | "last" | "readOnly">;
15
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,17 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { ConditionConnector } from "../ConditionConnector/ConditionConnector.js";
4
+ import { AddButtonRow } from "./ConditionAddButton.styles.js";
5
+ const ConditionAddButton = forwardRef(({
6
+ children,
7
+ withConnector = false,
8
+ connectorProps,
9
+ ...rest
10
+ }, ref) => /* @__PURE__ */ jsxs(AddButtonRow, { ref, ...rest, children: [
11
+ withConnector && /* @__PURE__ */ jsx(ConditionConnector, { last: true, ...connectorProps }),
12
+ children
13
+ ] }));
14
+ ConditionAddButton.displayName = "ConditionAddButton";
15
+ export {
16
+ ConditionAddButton
17
+ };
@@ -0,0 +1 @@
1
+ export declare const AddButtonRow: import('styled-components').StyledComponent<"div", any, {}, never>;
@@ -0,0 +1,8 @@
1
+ import styled from "styled-components";
2
+ const AddButtonRow = /* @__PURE__ */ styled.div.withConfig({
3
+ displayName: "ConditionAddButtonstyles__AddButtonRow",
4
+ componentId: "sc-1u66kfc-0"
5
+ })(["display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:12px;"]);
6
+ export {
7
+ AddButtonRow
8
+ };
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
3
+ import { ConditionConnectorProps } from '../ConditionConnector/ConditionConnector.types';
4
+ type ConditionAddButtonOwnProps = {
5
+ /** The add control rendered by the consuming app (e.g. a ghost ds-button). */
6
+ children: ReactNode;
7
+ /** Draw a `ConditionConnector` before the control so it hangs off the row tree line. */
8
+ withConnector?: boolean;
9
+ /** Props forwarded to the connector when `withConnector` is set. */
10
+ connectorProps?: Pick<ConditionConnectorProps, 'first' | 'last' | 'readOnly'>;
11
+ };
12
+ export type ConditionAddButtonProps = WithHTMLAttributes<HTMLDivElement, ConditionAddButtonOwnProps>;
13
+ export {};
@@ -0,0 +1,14 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * The tree-line connector that links an entity chip to its condition rows and the
4
+ * add-condition button. Ported from `@synerise/ds-condition`'s row connector.
5
+ */
6
+ export declare const ConditionConnector: React.ForwardRefExoticComponent<{
7
+ first?: boolean;
8
+ last?: boolean;
9
+ readOnly?: boolean;
10
+ } & Omit<React.HTMLAttributes<HTMLSpanElement>, keyof {
11
+ first?: boolean;
12
+ last?: boolean;
13
+ readOnly?: boolean;
14
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1,13 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Connector } from "./ConditionConnector.styles.js";
4
+ const ConditionConnector = forwardRef(({
5
+ first,
6
+ last,
7
+ readOnly,
8
+ ...rest
9
+ }, ref) => /* @__PURE__ */ jsx(Connector, { ref, $first: first, $last: last, $readOnly: readOnly, ...rest }));
10
+ ConditionConnector.displayName = "ConditionConnector";
11
+ export {
12
+ ConditionConnector
13
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The tree-line connector cell (ported from ds-condition's `ConditionConnections`).
3
+ *
4
+ * The horizontal stub is drawn with `::before`; the vertical line with `::after`. Crucially the
5
+ * cell *stretches to its row's full height* (`align-self: stretch`, no fixed height) so the
6
+ * vertical line only ever has to fill its own cell and then bridge the fixed inter-row gap
7
+ * (`CONDITION_ROWS_GAP`) to reach the next connector. This makes the line length independent of
8
+ * the row's content — multi-line or custom error messages no longer break the connection.
9
+ */
10
+ export declare const Connector: import('styled-components').StyledComponent<"span", any, {
11
+ $first?: boolean;
12
+ $last?: boolean;
13
+ $readOnly?: boolean;
14
+ }, never>;
@@ -0,0 +1,25 @@
1
+ import styled from "styled-components";
2
+ import { CONDITION_ROWS_GAP } from "../../constants.js";
3
+ const Connector = /* @__PURE__ */ styled.span.withConfig({
4
+ displayName: "ConditionConnectorstyles__Connector",
5
+ componentId: "sc-1vrdhzn-0"
6
+ })(["display:flex;width:32px;min-width:32px;min-height:32px;margin:0;position:relative;align-self:stretch;&:before{position:absolute;content:'';width:", ";height:1px;top:16px;left:", ";background-color:", ";}&:after{display:", ";position:absolute;content:'';width:1px;left:50%;background-color:", ";top:", ";bottom:", ";}"], ({
7
+ $first
8
+ }) => $first ? "100%" : "16px", ({
9
+ $first
10
+ }) => $first ? "0" : "16px", ({
11
+ theme
12
+ }) => theme.palette["grey-300"], ({
13
+ $first,
14
+ $last,
15
+ $readOnly
16
+ }) => $first && $last || $last && $readOnly ? "none" : "flex", ({
17
+ theme
18
+ }) => theme.palette["grey-300"], ({
19
+ $first
20
+ }) => $first ? "16px" : "0", ({
21
+ $last
22
+ }) => $last ? "calc(100% - 16px)" : `-${CONDITION_ROWS_GAP}px`);
23
+ export {
24
+ Connector
25
+ };
@@ -0,0 +1,11 @@
1
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
2
+ type ConditionConnectorOwnProps = {
3
+ /** First row in the group — draws a full-width horizontal stub. */
4
+ first?: boolean;
5
+ /** Last row in the group — stops the vertical line half-way down. */
6
+ last?: boolean;
7
+ /** Read-only conditions hide the trailing vertical line on the last row. */
8
+ readOnly?: boolean;
9
+ };
10
+ export type ConditionConnectorProps = WithHTMLAttributes<HTMLSpanElement, ConditionConnectorOwnProps>;
11
+ export {};
@@ -0,0 +1,16 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Wrapper for the entity/context area at the start of a condition group. Lays out one or more
4
+ * chip slots in a row (12px gap by default) and renders an optional `errorMessage` below.
5
+ * Presentational only — the consuming app renders the actual chip(s) inside (e.g. a `ds-button`
6
+ * in custom-color mode, or `ds-context-selector`).
7
+ */
8
+ export declare const ConditionEntity: React.ForwardRefExoticComponent<{
9
+ children: React.ReactNode;
10
+ gap?: number | string;
11
+ errorMessage?: React.ReactNode;
12
+ } & Omit<React.HTMLAttributes<HTMLSpanElement>, keyof {
13
+ children: React.ReactNode;
14
+ gap?: number | string;
15
+ errorMessage?: React.ReactNode;
16
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1,18 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { toCssSize } from "@synerise/ds-utils";
4
+ import { ErrorMessage } from "../../errorMessage.styles.js";
5
+ import { EntityOuter, EntityRow } from "./ConditionEntity.styles.js";
6
+ const ConditionEntity = forwardRef(({
7
+ children,
8
+ gap = 12,
9
+ errorMessage,
10
+ ...rest
11
+ }, ref) => /* @__PURE__ */ jsxs(EntityOuter, { ref, ...rest, children: [
12
+ /* @__PURE__ */ jsx(EntityRow, { $gap: toCssSize(gap), children }),
13
+ errorMessage && /* @__PURE__ */ jsx(ErrorMessage, { children: errorMessage })
14
+ ] }));
15
+ ConditionEntity.displayName = "ConditionEntity";
16
+ export {
17
+ ConditionEntity
18
+ };
@@ -0,0 +1,4 @@
1
+ export declare const EntityOuter: import('styled-components').StyledComponent<"span", any, {}, never>;
2
+ export declare const EntityRow: import('styled-components').StyledComponent<"span", any, {
3
+ $gap: string;
4
+ }, never>;
@@ -0,0 +1,15 @@
1
+ import styled from "styled-components";
2
+ const EntityOuter = /* @__PURE__ */ styled.span.withConfig({
3
+ displayName: "ConditionEntitystyles__EntityOuter",
4
+ componentId: "sc-16cm7bd-0"
5
+ })(["display:inline-flex;flex-direction:column;align-items:flex-start;"]);
6
+ const EntityRow = /* @__PURE__ */ styled.span.withConfig({
7
+ displayName: "ConditionEntitystyles__EntityRow",
8
+ componentId: "sc-16cm7bd-1"
9
+ })(["display:inline-flex;flex-direction:row;align-items:flex-start;gap:", ";"], ({
10
+ $gap
11
+ }) => $gap);
12
+ export {
13
+ EntityOuter,
14
+ EntityRow
15
+ };
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from 'react';
2
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
3
+ type ConditionEntityOwnProps = {
4
+ /** The entity/context chip(s) rendered by the consuming app (e.g. a ds-button or ds-context-selector). */
5
+ children: ReactNode;
6
+ /** Gap between multiple entity slots. A number is treated as px. @default 12 */
7
+ gap?: number | string;
8
+ /** Optional error message rendered below the entity. */
9
+ errorMessage?: ReactNode;
10
+ };
11
+ export type ConditionEntityProps = WithHTMLAttributes<HTMLSpanElement, ConditionEntityOwnProps>;
12
+ export {};
@@ -0,0 +1,14 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Outermost layout wrapper for a single condition: the entity wrapper on the left and its
4
+ * `ConditionRows` on the right, separated by `gap` (12px default). Forward its ref and pass the
5
+ * node as `getPopupContainer` for the enclosed dropdowns so their popovers share one stacking
6
+ * context (fixes popover z-index issues).
7
+ */
8
+ export declare const ConditionGroup: React.ForwardRefExoticComponent<{
9
+ children: React.ReactNode;
10
+ gap?: number | string;
11
+ } & Omit<React.HTMLAttributes<HTMLDivElement>, keyof {
12
+ children: React.ReactNode;
13
+ gap?: number | string;
14
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,13 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { toCssSize } from "@synerise/ds-utils";
4
+ import { Group } from "./ConditionGroup.styles.js";
5
+ const ConditionGroup = forwardRef(({
6
+ children,
7
+ gap = 12,
8
+ ...rest
9
+ }, ref) => /* @__PURE__ */ jsx(Group, { ref, $gap: toCssSize(gap), ...rest, children }));
10
+ ConditionGroup.displayName = "ConditionGroup";
11
+ export {
12
+ ConditionGroup
13
+ };
@@ -0,0 +1,3 @@
1
+ export declare const Group: import('styled-components').StyledComponent<"div", any, {
2
+ $gap: string;
3
+ }, never>;
@@ -0,0 +1,10 @@
1
+ import styled from "styled-components";
2
+ const Group = /* @__PURE__ */ styled.div.withConfig({
3
+ displayName: "ConditionGroupstyles__Group",
4
+ componentId: "sc-pfmgu2-0"
5
+ })(["display:flex;flex-direction:row;align-items:flex-start;justify-content:flex-start;gap:", ";"], ({
6
+ $gap
7
+ }) => $gap);
8
+ export {
9
+ Group
10
+ };
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from 'react';
2
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
3
+ type ConditionGroupOwnProps = {
4
+ children: ReactNode;
5
+ /** Gap between the entity wrapper and the rows. A number is treated as px. @default 12 */
6
+ gap?: number | string;
7
+ };
8
+ export type ConditionGroupProps = WithHTMLAttributes<HTMLDivElement, ConditionGroupOwnProps>;
9
+ export {};
@@ -0,0 +1,17 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * The remove (✕) control for a condition row. Revealed when the enclosing `ConditionRow` is
4
+ * hovered or focused by default; set `revealOnRowHover={false}` to keep it always visible.
5
+ *
6
+ * The icon carries no text, so the accessible name comes from `aria-label` — translated, since a
7
+ * consuming app renders this in the user's locale. Pass `aria-label` to override it.
8
+ */
9
+ export declare const ConditionRemove: React.ForwardRefExoticComponent<{
10
+ onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
11
+ revealOnRowHover?: boolean;
12
+ disabled?: boolean;
13
+ } & Omit<React.HTMLAttributes<HTMLButtonElement>, keyof {
14
+ onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
15
+ revealOnRowHover?: boolean;
16
+ disabled?: boolean;
17
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,24 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { useIntl } from "react-intl";
4
+ import Icon, { CloseS } from "@synerise/ds-icon";
5
+ import { CONDITION_REMOVE_CLASS } from "../../constants.js";
6
+ import { RemoveButton } from "./ConditionRemove.styles.js";
7
+ const ConditionRemove = forwardRef(({
8
+ onClick,
9
+ revealOnRowHover = true,
10
+ disabled = false,
11
+ "aria-label": ariaLabel,
12
+ className,
13
+ ...rest
14
+ }, ref) => {
15
+ const intl = useIntl();
16
+ return /* @__PURE__ */ jsx(RemoveButton, { ref, $reveal: revealOnRowHover, onClick, disabled, "aria-label": ariaLabel ?? intl.formatMessage({
17
+ id: "DS.CONDITION-BLOCKS.REMOVE",
18
+ defaultMessage: "Remove"
19
+ }), className: [CONDITION_REMOVE_CLASS, className].filter(Boolean).join(" "), ...rest, children: /* @__PURE__ */ jsx(Icon, { component: /* @__PURE__ */ jsx(CloseS, {}) }) });
20
+ });
21
+ ConditionRemove.displayName = "ConditionRemove";
22
+ export {
23
+ ConditionRemove
24
+ };
@@ -0,0 +1,5 @@
1
+ export declare const RemoveButton: import('styled-components').StyledComponent<"button", any, {
2
+ type: "button";
3
+ } & {
4
+ $reveal: boolean;
5
+ }, "type">;
@@ -0,0 +1,16 @@
1
+ import styled, { css } from "styled-components";
2
+ const RemoveButton = /* @__PURE__ */ styled.button.attrs({
3
+ type: "button"
4
+ }).withConfig({
5
+ displayName: "ConditionRemovestyles__RemoveButton",
6
+ componentId: "sc-1508kcm-0"
7
+ })(["display:flex;flex:0 0 auto;align-items:center;justify-content:center;width:24px;height:32px;padding:0;border:none;background:transparent;color:", ";cursor:pointer;transition:all 0.3s ease;", " &:disabled{cursor:not-allowed;color:", ";}"], ({
8
+ theme
9
+ }) => theme.palette["red-600"], ({
10
+ $reveal
11
+ }) => $reveal && css(["opacity:0;pointer-events:none;&:focus-visible{opacity:1;pointer-events:auto;}"]), ({
12
+ theme
13
+ }) => theme.palette["grey-400"]);
14
+ export {
15
+ RemoveButton
16
+ };
@@ -0,0 +1,10 @@
1
+ import { MouseEvent } from 'react';
2
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
3
+ type ConditionRemoveOwnProps = {
4
+ onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
5
+ /** Hidden until the containing `ConditionRow` is hovered. @default true */
6
+ revealOnRowHover?: boolean;
7
+ disabled?: boolean;
8
+ };
9
+ export type ConditionRemoveProps = WithHTMLAttributes<HTMLButtonElement, ConditionRemoveOwnProps>;
10
+ export {};
@@ -0,0 +1,21 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Horizontal flex row of slots / text / triggers. Fills its parent but never overflows
4
+ * (`min-width: 0`); defers sizing to the `ConditionSlot`s inside it. Reveals a `ConditionRemove`
5
+ * descendant on hover. Pass `connector` to render a leading `ConditionConnector`; pass
6
+ * `errorMessage` to render an error below the slots (aligned with the first slot) — the connector's
7
+ * vertical line extends automatically to reach the next row.
8
+ */
9
+ export declare const ConditionRow: React.ForwardRefExoticComponent<{
10
+ children: React.ReactNode;
11
+ gap?: number | string;
12
+ align?: import('./ConditionRow.types').ConditionRowAlign;
13
+ errorMessage?: React.ReactNode;
14
+ connector?: import('../..').ConditionConnectorProps;
15
+ } & Omit<React.HTMLAttributes<HTMLDivElement>, keyof {
16
+ children: React.ReactNode;
17
+ gap?: number | string;
18
+ align?: import('./ConditionRow.types').ConditionRowAlign;
19
+ errorMessage?: React.ReactNode;
20
+ connector?: import('../..').ConditionConnectorProps;
21
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,24 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { toCssSize } from "@synerise/ds-utils";
4
+ import { ErrorMessage } from "../../errorMessage.styles.js";
5
+ import { ConditionConnector } from "../ConditionConnector/ConditionConnector.js";
6
+ import { RowOuter, Content, Row } from "./ConditionRow.styles.js";
7
+ const ConditionRow = forwardRef(({
8
+ children,
9
+ gap = 12,
10
+ align = "start",
11
+ errorMessage,
12
+ connector,
13
+ ...rest
14
+ }, ref) => /* @__PURE__ */ jsxs(RowOuter, { ref, $gap: toCssSize(gap), ...rest, children: [
15
+ connector && /* @__PURE__ */ jsx(ConditionConnector, { ...connector }),
16
+ /* @__PURE__ */ jsxs(Content, { children: [
17
+ /* @__PURE__ */ jsx(Row, { $gap: toCssSize(gap), $align: align, children }),
18
+ errorMessage && /* @__PURE__ */ jsx(ErrorMessage, { children: errorMessage })
19
+ ] })
20
+ ] }));
21
+ ConditionRow.displayName = "ConditionRow";
22
+ export {
23
+ ConditionRow
24
+ };
@@ -0,0 +1,9 @@
1
+ import { ConditionRowAlign } from './ConditionRow.types';
2
+ export declare const RowOuter: import('styled-components').StyledComponent<"div", any, {
3
+ $gap: string;
4
+ }, never>;
5
+ export declare const Content: import('styled-components').StyledComponent<"div", any, {}, never>;
6
+ export declare const Row: import('styled-components').StyledComponent<"div", any, {
7
+ $gap: string;
8
+ $align: ConditionRowAlign;
9
+ }, never>;
@@ -0,0 +1,31 @@
1
+ import styled, { css } from "styled-components";
2
+ import { CONDITION_REMOVE_CLASS } from "../../constants.js";
3
+ const ALIGN_ITEMS = {
4
+ start: "flex-start",
5
+ center: "center",
6
+ baseline: "baseline"
7
+ };
8
+ const revealRemove = /* @__PURE__ */ css(["opacity:1;pointer-events:auto;"]);
9
+ const RowOuter = /* @__PURE__ */ styled.div.withConfig({
10
+ displayName: "ConditionRowstyles__RowOuter",
11
+ componentId: "sc-19gru60-0"
12
+ })(["display:flex;flex-direction:row;align-items:stretch;gap:", ";flex-grow:1;min-width:0;&:hover .", "{", "}&:focus-within .", "{", "}"], ({
13
+ $gap
14
+ }) => $gap, CONDITION_REMOVE_CLASS, revealRemove, CONDITION_REMOVE_CLASS, revealRemove);
15
+ const Content = /* @__PURE__ */ styled.div.withConfig({
16
+ displayName: "ConditionRowstyles__Content",
17
+ componentId: "sc-19gru60-1"
18
+ })(["display:flex;flex-direction:column;flex-grow:1;min-width:0;"]);
19
+ const Row = /* @__PURE__ */ styled.div.withConfig({
20
+ displayName: "ConditionRowstyles__Row",
21
+ componentId: "sc-19gru60-2"
22
+ })(["display:flex;flex-direction:row;justify-content:flex-start;align-items:", ";gap:", ";min-width:0;"], ({
23
+ $align
24
+ }) => ALIGN_ITEMS[$align], ({
25
+ $gap
26
+ }) => $gap);
27
+ export {
28
+ Content,
29
+ Row,
30
+ RowOuter
31
+ };
@@ -0,0 +1,22 @@
1
+ import { ReactNode } from 'react';
2
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
3
+ import { ConditionConnectorProps } from '../ConditionConnector/ConditionConnector.types';
4
+ /** Cross-axis alignment of a row's children. */
5
+ export type ConditionRowAlign = 'start' | 'center' | 'baseline';
6
+ type ConditionRowOwnProps = {
7
+ children: ReactNode;
8
+ /** Gap between children. A number is treated as px. @default 12 */
9
+ gap?: number | string;
10
+ /** Cross-axis alignment. Use `center` / `baseline` for text-interleaved layouts. @default 'start' */
11
+ align?: ConditionRowAlign;
12
+ /** Optional error message rendered below the slots, aligned with the first slot. */
13
+ errorMessage?: ReactNode;
14
+ /**
15
+ * When set, the row renders a leading `ConditionConnector` with these props — the consumer no
16
+ * longer composes one as a child. The connector's line spans the row automatically, so it stays
17
+ * connected even with a multi-line or custom `errorMessage`.
18
+ */
19
+ connector?: ConditionConnectorProps;
20
+ };
21
+ export type ConditionRowProps = WithHTMLAttributes<HTMLDivElement, ConditionRowOwnProps>;
22
+ export {};
@@ -0,0 +1,13 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Vertical container for the `ConditionRow`s (and add button) that sit next to a
4
+ * `ConditionEntity`. Fills the remaining width, stays shrinkable (`min-width: 0`) so the
5
+ * rows never overflow, and sets the inter-row gap (16px by default; a design token later).
6
+ */
7
+ export declare const ConditionRows: React.ForwardRefExoticComponent<{
8
+ children: React.ReactNode;
9
+ gap?: number | string;
10
+ } & Omit<React.HTMLAttributes<HTMLDivElement>, keyof {
11
+ children: React.ReactNode;
12
+ gap?: number | string;
13
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,14 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { toCssSize } from "@synerise/ds-utils";
4
+ import { CONDITION_ROWS_GAP } from "../../constants.js";
5
+ import { Rows } from "./ConditionRows.styles.js";
6
+ const ConditionRows = forwardRef(({
7
+ children,
8
+ gap = CONDITION_ROWS_GAP,
9
+ ...rest
10
+ }, ref) => /* @__PURE__ */ jsx(Rows, { ref, $gap: toCssSize(gap), ...rest, children }));
11
+ ConditionRows.displayName = "ConditionRows";
12
+ export {
13
+ ConditionRows
14
+ };
@@ -0,0 +1,3 @@
1
+ export declare const Rows: import('styled-components').StyledComponent<"div", any, {
2
+ $gap: string;
3
+ }, never>;
@@ -0,0 +1,10 @@
1
+ import styled from "styled-components";
2
+ const Rows = /* @__PURE__ */ styled.div.withConfig({
3
+ displayName: "ConditionRowsstyles__Rows",
4
+ componentId: "sc-1v5urct-0"
5
+ })(["display:flex;flex-direction:column;align-items:stretch;flex-grow:1;min-width:0;gap:", ";"], ({
6
+ $gap
7
+ }) => $gap);
8
+ export {
9
+ Rows
10
+ };
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
3
+ type ConditionRowsOwnProps = {
4
+ children: ReactNode;
5
+ /**
6
+ * Vertical gap between rows (and the add button). A number is treated as px.
7
+ * Defaults to 16px — to be replaced by a design token in follow-up work.
8
+ * @default 16
9
+ */
10
+ gap?: number | string;
11
+ };
12
+ export type ConditionRowsProps = WithHTMLAttributes<HTMLDivElement, ConditionRowsOwnProps>;
13
+ export {};
@@ -0,0 +1,26 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Sizing wrapper for a single control in a `ConditionRow`. Choose a `variant` preset
4
+ * (`rigid` / `fill` / `shrink`) or set `grow` / `shrink` / `basis` / `minWidth` / `maxWidth`
5
+ * explicitly; the internal `min-width: 0` cascade lets it shrink below intrinsic width. Renders
6
+ * an optional `errorMessage` below the control.
7
+ */
8
+ export declare const ConditionSlot: React.ForwardRefExoticComponent<{
9
+ children: React.ReactNode;
10
+ variant?: import('./ConditionSlot.types').ConditionSlotVariant;
11
+ grow?: number;
12
+ shrink?: number;
13
+ basis?: string;
14
+ minWidth?: number | string;
15
+ maxWidth?: number | string;
16
+ errorMessage?: React.ReactNode;
17
+ } & Omit<React.HTMLAttributes<HTMLDivElement>, keyof {
18
+ children: React.ReactNode;
19
+ variant?: import('./ConditionSlot.types').ConditionSlotVariant;
20
+ grow?: number;
21
+ shrink?: number;
22
+ basis?: string;
23
+ minWidth?: number | string;
24
+ maxWidth?: number | string;
25
+ errorMessage?: React.ReactNode;
26
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,22 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { ErrorMessage } from "../../errorMessage.styles.js";
4
+ import { Slot, SlotContent } from "./ConditionSlot.styles.js";
5
+ const ConditionSlot = forwardRef(({
6
+ children,
7
+ variant = "rigid",
8
+ grow,
9
+ shrink,
10
+ basis = "auto",
11
+ minWidth,
12
+ maxWidth,
13
+ errorMessage,
14
+ ...rest
15
+ }, ref) => /* @__PURE__ */ jsxs(Slot, { ref, $variant: variant, $grow: grow, $shrink: shrink, $basis: basis, $minWidth: minWidth, $maxWidth: maxWidth, ...rest, children: [
16
+ /* @__PURE__ */ jsx(SlotContent, { children }),
17
+ errorMessage && /* @__PURE__ */ jsx(ErrorMessage, { children: errorMessage })
18
+ ] }));
19
+ ConditionSlot.displayName = "ConditionSlot";
20
+ export {
21
+ ConditionSlot
22
+ };
@@ -0,0 +1,10 @@
1
+ import { ConditionSlotVariant } from './ConditionSlot.types';
2
+ export declare const Slot: import('styled-components').StyledComponent<"div", any, {
3
+ $variant: ConditionSlotVariant;
4
+ $grow?: number;
5
+ $shrink?: number;
6
+ $basis: string;
7
+ $minWidth?: number | string;
8
+ $maxWidth?: number | string;
9
+ }, never>;
10
+ export declare const SlotContent: import('styled-components').StyledComponent<"div", any, {}, never>;
@@ -0,0 +1,41 @@
1
+ import styled, { css } from "styled-components";
2
+ import { toCssSize } from "@synerise/ds-utils";
3
+ import { CONDITION_REMOVE_CLASS } from "../../constants.js";
4
+ const VARIANT_FLEX = {
5
+ rigid: {
6
+ grow: 0,
7
+ shrink: 0
8
+ },
9
+ fill: {
10
+ grow: 30,
11
+ shrink: 1
12
+ },
13
+ shrink: {
14
+ grow: 0,
15
+ shrink: 400
16
+ }
17
+ };
18
+ const Slot = /* @__PURE__ */ styled.div.withConfig({
19
+ displayName: "ConditionSlotstyles__Slot",
20
+ componentId: "sc-10scp3m-0"
21
+ })(["display:flex;flex-direction:column;min-width:0;flex-grow:", ";flex-shrink:", ";flex-basis:", ";", " ", " .ds-input-group-item{min-width:0;}"], ({
22
+ $variant,
23
+ $grow
24
+ }) => $grow ?? VARIANT_FLEX[$variant].grow, ({
25
+ $variant,
26
+ $shrink
27
+ }) => $shrink ?? VARIANT_FLEX[$variant].shrink, ({
28
+ $basis
29
+ }) => $basis, ({
30
+ $minWidth
31
+ }) => $minWidth !== void 0 && css(["min-width:", ";"], toCssSize($minWidth)), ({
32
+ $maxWidth
33
+ }) => $maxWidth !== void 0 && css(["max-width:", ";"], toCssSize($maxWidth)));
34
+ const SlotContent = /* @__PURE__ */ styled.div.withConfig({
35
+ displayName: "ConditionSlotstyles__SlotContent",
36
+ componentId: "sc-10scp3m-1"
37
+ })(["display:flex;min-width:0;> *{min-width:0;}> .", "{margin-left:8px;}"], CONDITION_REMOVE_CLASS);
38
+ export {
39
+ Slot,
40
+ SlotContent
41
+ };
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from 'react';
2
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
3
+ /**
4
+ * Sizing preset mirroring `@synerise/ds-condition`'s slots: `rigid`=operator, `fill`=factor,
5
+ * `shrink`=parameter.
6
+ */
7
+ export type ConditionSlotVariant = 'rigid' | 'fill' | 'shrink';
8
+ type ConditionSlotOwnProps = {
9
+ children: ReactNode;
10
+ /** Sizing preset. Overridden by explicit `grow` / `shrink`. @default 'rigid' */
11
+ variant?: ConditionSlotVariant;
12
+ grow?: number;
13
+ shrink?: number;
14
+ basis?: string;
15
+ minWidth?: number | string;
16
+ maxWidth?: number | string;
17
+ /** Optional error message rendered below the control. */
18
+ errorMessage?: ReactNode;
19
+ };
20
+ export type ConditionSlotProps = WithHTMLAttributes<HTMLDivElement, ConditionSlotOwnProps>;
21
+ export {};
@@ -0,0 +1,13 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Inline, non-interactive text slot used to interleave plain text with controls inside a
4
+ * `ConditionRow` — e.g. "Show only [N] items with the same [attribute]". Vertically centred
5
+ * against pill-height controls.
6
+ */
7
+ export declare const ConditionTextSlot: React.ForwardRefExoticComponent<{
8
+ children: React.ReactNode;
9
+ muted?: boolean;
10
+ } & Omit<React.HTMLAttributes<HTMLSpanElement>, keyof {
11
+ children: React.ReactNode;
12
+ muted?: boolean;
13
+ }> & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1,12 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Text } from "./ConditionTextSlot.styles.js";
4
+ const ConditionTextSlot = forwardRef(({
5
+ children,
6
+ muted = false,
7
+ ...rest
8
+ }, ref) => /* @__PURE__ */ jsx(Text, { ref, $muted: muted, ...rest, children }));
9
+ ConditionTextSlot.displayName = "ConditionTextSlot";
10
+ export {
11
+ ConditionTextSlot
12
+ };
@@ -0,0 +1,3 @@
1
+ export declare const Text: import('styled-components').StyledComponent<"span", any, {
2
+ $muted?: boolean;
3
+ }, never>;
@@ -0,0 +1,11 @@
1
+ import styled from "styled-components";
2
+ const Text = /* @__PURE__ */ styled.span.withConfig({
3
+ displayName: "ConditionTextSlotstyles__Text",
4
+ componentId: "sc-13tqdvh-0"
5
+ })(["flex:0 0 auto;align-self:center;white-space:nowrap;font-size:13px;line-height:1.85;color:", ";"], ({
6
+ theme,
7
+ $muted
8
+ }) => theme.palette[$muted ? "grey-500" : "grey-800"]);
9
+ export {
10
+ Text
11
+ };
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from 'react';
2
+ import { WithHTMLAttributes } from '@synerise/ds-utils';
3
+ type ConditionTextSlotOwnProps = {
4
+ children: ReactNode;
5
+ /** Render in a lighter, secondary colour. @default false */
6
+ muted?: boolean;
7
+ };
8
+ export type ConditionTextSlotProps = WithHTMLAttributes<HTMLSpanElement, ConditionTextSlotOwnProps>;
9
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Stable class applied to `ConditionRemove` so a parent `ConditionRow` can reveal it on hover
3
+ * without the two components sharing a styled-component reference across files.
4
+ */
5
+ export declare const CONDITION_REMOVE_CLASS = "ds-condition-remove";
6
+ /**
7
+ * Vertical gap between stacked `ConditionRow`s (and the add button). Shared so the connector's
8
+ * vertical line knows exactly how far to reach the next row — the only spacing it must bridge,
9
+ * now that the connector cell stretches to its own row's full height.
10
+ */
11
+ export declare const CONDITION_ROWS_GAP = 16;
@@ -0,0 +1,6 @@
1
+ const CONDITION_REMOVE_CLASS = "ds-condition-remove";
2
+ const CONDITION_ROWS_GAP = 16;
3
+ export {
4
+ CONDITION_REMOVE_CLASS,
5
+ CONDITION_ROWS_GAP
6
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Shared error label for the block error slots. Reuses ds-typography's `ErrorText` (red-600) and
3
+ * overrides its default `margin-bottom: 4px` — here the message sits *below* its slot, so it needs
4
+ * a top margin instead.
5
+ */
6
+ export declare const ErrorMessage: import('styled-components').StyledComponent<"div", any, {}, never>;
@@ -0,0 +1,9 @@
1
+ import styled from "styled-components";
2
+ import { ErrorText } from "@synerise/ds-typography";
3
+ const ErrorMessage = /* @__PURE__ */ styled(ErrorText).withConfig({
4
+ displayName: "errorMessagestyles__ErrorMessage",
5
+ componentId: "sc-105izfy-0"
6
+ })(["margin-top:8px;margin-bottom:0;font-size:12px;line-height:1.34;"]);
7
+ export {
8
+ ErrorMessage
9
+ };
@@ -0,0 +1,18 @@
1
+ export { ConditionAddButton } from './components/ConditionAddButton/ConditionAddButton';
2
+ export type { ConditionAddButtonProps } from './components/ConditionAddButton/ConditionAddButton.types';
3
+ export { ConditionConnector } from './components/ConditionConnector/ConditionConnector';
4
+ export type { ConditionConnectorProps } from './components/ConditionConnector/ConditionConnector.types';
5
+ export { ConditionEntity } from './components/ConditionEntity/ConditionEntity';
6
+ export type { ConditionEntityProps } from './components/ConditionEntity/ConditionEntity.types';
7
+ export { ConditionGroup } from './components/ConditionGroup/ConditionGroup';
8
+ export type { ConditionGroupProps } from './components/ConditionGroup/ConditionGroup.types';
9
+ export { ConditionRemove } from './components/ConditionRemove/ConditionRemove';
10
+ export type { ConditionRemoveProps } from './components/ConditionRemove/ConditionRemove.types';
11
+ export { ConditionRow } from './components/ConditionRow/ConditionRow';
12
+ export type { ConditionRowAlign, ConditionRowProps, } from './components/ConditionRow/ConditionRow.types';
13
+ export { ConditionRows } from './components/ConditionRows/ConditionRows';
14
+ export type { ConditionRowsProps } from './components/ConditionRows/ConditionRows.types';
15
+ export { ConditionSlot } from './components/ConditionSlot/ConditionSlot';
16
+ export type { ConditionSlotProps, ConditionSlotVariant, } from './components/ConditionSlot/ConditionSlot.types';
17
+ export { ConditionTextSlot } from './components/ConditionTextSlot/ConditionTextSlot';
18
+ export type { ConditionTextSlotProps } from './components/ConditionTextSlot/ConditionTextSlot.types';
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ import { ConditionAddButton } from "./components/ConditionAddButton/ConditionAddButton.js";
2
+ import { ConditionConnector } from "./components/ConditionConnector/ConditionConnector.js";
3
+ import { ConditionEntity } from "./components/ConditionEntity/ConditionEntity.js";
4
+ import { ConditionGroup } from "./components/ConditionGroup/ConditionGroup.js";
5
+ import { ConditionRemove } from "./components/ConditionRemove/ConditionRemove.js";
6
+ import { ConditionRow } from "./components/ConditionRow/ConditionRow.js";
7
+ import { ConditionRows } from "./components/ConditionRows/ConditionRows.js";
8
+ import { ConditionSlot } from "./components/ConditionSlot/ConditionSlot.js";
9
+ import { ConditionTextSlot } from "./components/ConditionTextSlot/ConditionTextSlot.js";
10
+ export {
11
+ ConditionAddButton,
12
+ ConditionConnector,
13
+ ConditionEntity,
14
+ ConditionGroup,
15
+ ConditionRemove,
16
+ ConditionRow,
17
+ ConditionRows,
18
+ ConditionSlot,
19
+ ConditionTextSlot
20
+ };
@@ -0,0 +1 @@
1
+ import "@testing-library/jest-dom";
File without changes
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@synerise/ds-condition-blocks",
3
+ "version": "0.1.0",
4
+ "description": "Composable building blocks for filtering-condition layouts in the Synerise Design System",
5
+ "license": "ISC",
6
+ "repository": "Synerise/synerise-design",
7
+ "main": "dist/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./dist/*.js": "./dist/*.js",
15
+ "./dist/*": "./dist/*.js"
16
+ },
17
+ "files": [
18
+ "/dist",
19
+ "CHANGELOG.md",
20
+ "CLAUDE.md",
21
+ "README.md",
22
+ "package.json",
23
+ "LICENSE.md"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "scripts": {
29
+ "build": "vite build",
30
+ "build:watch": "vite build --watch",
31
+ "pack:ci": "pnpm pack --pack-destination ../../storybook/storybook-static/static",
32
+ "prepublish": "pnpm run build",
33
+ "test": "vitest run",
34
+ "test:watch": "vitest",
35
+ "types": "tsc --noEmit",
36
+ "check:circular-dependencies": "madge --circular --extensions ts,tsx,js,jsx --ts-config tsconfig.json src/ --exclude '/dist/'",
37
+ "upgrade:ds": "ncu -f \"@synerise/ds-*\" -u"
38
+ },
39
+ "sideEffects": [
40
+ "dist/style/*",
41
+ "*.less"
42
+ ],
43
+ "types": "dist/index.d.ts",
44
+ "dependencies": {
45
+ "@synerise/ds-icon": "^2.1.3",
46
+ "@synerise/ds-typography": "^2.0.5",
47
+ "@synerise/ds-utils": "^2.2.0"
48
+ },
49
+ "peerDependencies": {
50
+ "@synerise/ds-core": "*",
51
+ "react": ">=16.9.0 <= 18.3.1",
52
+ "react-intl": "^6.8.7",
53
+ "styled-components": "^5.3.3",
54
+ "vitest": "4"
55
+ },
56
+ "gitHead": "5e795fa4fd23f6b07277edb517a84bb9b5b6d256"
57
+ }