cetec-design-system 2.2.2-next.0 → 2.3.7
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/dist/{cetec-preset-CcvrY8wh.js → cetec-preset-CZJA5UR0.js} +1696 -1331
- package/dist/cetec-preset-CZJA5UR0.js.map +1 -0
- package/dist/index.js +12655 -9360
- package/dist/index.js.map +1 -1
- package/dist/panda.buildinfo.json +461 -365
- package/dist/playroom-static.css +68887 -180258
- package/dist/preset.js +1 -1
- package/dist/specs/recipes.json +126 -25
- package/dist/styles.css +1315 -642
- package/dist/types/index.d.ts +3001 -273
- package/dist/types/preset.d.ts +15 -0
- package/package.json +6 -1
- package/src/recipes/autocomplete.ts +266 -0
- package/src/recipes/calendar.ts +92 -0
- package/src/recipes/chip.ts +6 -0
- package/src/recipes/dateMenus.ts +40 -0
- package/src/recipes/dateTimeMenus.ts +43 -0
- package/src/recipes/menu.ts +13 -1
- package/src/recipes/modal.ts +1 -1
- package/src/recipes/recipes-slot.ts +7 -2
- package/src/recipes/segmentedFields.ts +192 -0
- package/src/recipes/segmentedInputs.ts +106 -0
- package/src/recipes/text.ts +32 -28
- package/src/recipes/timeMenus.ts +110 -0
- package/src/styles/primitives/zIndex.ts +1 -0
- package/src/styles/semantics/colors.ts +44 -0
- package/src/styles/semantics/zIndex.ts +2 -0
- package/src/styles/utilities/conditions.ts +1 -0
- package/src/styles/utilities/transitions.ts +2 -1
- package/src/utils/dsChain.ts +113 -0
- package/src/utils/dsComponent.ts +44 -0
- package/src/utils/dsPart.ts +41 -0
- package/src/utils/splitProps.ts +15 -0
- package/dist/cetec-preset-CcvrY8wh.js.map +0 -1
- package/src/recipes/datePicker.ts +0 -230
- package/src/recipes/timePicker.ts +0 -206
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Attribute name that carries a resolved interaction chain on a portal root.
|
|
5
|
+
* Always lowercase and hyphenated; HTML lowercases attribute names, so a
|
|
6
|
+
* camelCase spelling would silently produce a different attribute.
|
|
7
|
+
*/
|
|
8
|
+
export const DS_CHAIN_ATTRIBUTE = 'data-ds-chain';
|
|
9
|
+
|
|
10
|
+
/** Separator written between chain nodes in the serialized attribute value. */
|
|
11
|
+
export const DS_CHAIN_SEPARATOR = '>';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Attribute marking the wrapper a portal's contents render into. Written
|
|
15
|
+
* unconditionally, including when the resolved chain is empty, so a consumer
|
|
16
|
+
* walking up the DOM can tell a portal boundary from an ordinary element and
|
|
17
|
+
* stop there instead of continuing into `document.body`.
|
|
18
|
+
*/
|
|
19
|
+
export const DS_PORTAL_ROOT_ATTRIBUTE = 'data-ds-portal-root';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Maximum number of chain nodes retained. The nearest nodes are kept because
|
|
23
|
+
* the leaf end of the chain is what identifies an interaction; page-level
|
|
24
|
+
* object identity is carried separately rather than through this chain.
|
|
25
|
+
*/
|
|
26
|
+
export const DS_CHAIN_MAX_DEPTH = 5;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Attribute carrying business-object identity. The application authors it — on
|
|
30
|
+
* a layout wrapper for legacy Perl screens, on individual elements on React
|
|
31
|
+
* screens. The design system never invents a value; it only copies one onto a
|
|
32
|
+
* portal root, which is the single place DOM ancestry cannot supply it.
|
|
33
|
+
*/
|
|
34
|
+
export const DS_OBJECT_ATTRIBUTE = 'data-track-object';
|
|
35
|
+
|
|
36
|
+
// Module-level constant so every reader outside a scope shares one identity.
|
|
37
|
+
// A fresh `[]` default would hand consumers a new value on each render and
|
|
38
|
+
// defeat the memoization in the provider.
|
|
39
|
+
const EMPTY_CHAIN: readonly string[] = Object.freeze([]);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Carries the `data-testid` values of the enclosing tagged elements, nearest
|
|
43
|
+
* last. React context walks the React tree rather than the DOM, so portaled
|
|
44
|
+
* content still resolves the chain of the subtree that rendered it.
|
|
45
|
+
*/
|
|
46
|
+
export const DsChainContext = createContext<readonly string[]>(EMPTY_CHAIN);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Returns the interaction chain for the current position in the React tree.
|
|
50
|
+
*
|
|
51
|
+
* Returns a shared empty array outside any scope, so the result is safe to read
|
|
52
|
+
* unconditionally.
|
|
53
|
+
*/
|
|
54
|
+
export const useDsChain = (): readonly string[] => useContext(DsChainContext);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Appends a `data-testid` value to a chain, keeping the nearest
|
|
58
|
+
* `DS_CHAIN_MAX_DEPTH` nodes.
|
|
59
|
+
*
|
|
60
|
+
* A value equal to the innermost node is dropped rather than repeated. Two
|
|
61
|
+
* supported arrangements produce that case: a component that opens a scope
|
|
62
|
+
* above its root and also writes the same id on an inner element, and a
|
|
63
|
+
* consumer that wraps a design-system component in `DsChainScope` using the
|
|
64
|
+
* `data-testid` that component already emits. Neither is an error, and a
|
|
65
|
+
* repeated node carries no information while it consumes one of five slots.
|
|
66
|
+
*
|
|
67
|
+
* Only the innermost node is compared. A legitimately recurring id further out
|
|
68
|
+
* — a nested grid inside a grid — still contributes, because the repeat there
|
|
69
|
+
* describes real structure.
|
|
70
|
+
*/
|
|
71
|
+
export const extendDsChain = (
|
|
72
|
+
chain: readonly string[],
|
|
73
|
+
testId: string,
|
|
74
|
+
): readonly string[] => {
|
|
75
|
+
if (chain[chain.length - 1] === testId) return chain;
|
|
76
|
+
|
|
77
|
+
const next = [...chain, testId];
|
|
78
|
+
|
|
79
|
+
return next.length > DS_CHAIN_MAX_DEPTH
|
|
80
|
+
? next.slice(-DS_CHAIN_MAX_DEPTH)
|
|
81
|
+
: next;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Serializes a chain for the `data-ds-chain` attribute.
|
|
86
|
+
*
|
|
87
|
+
* Returns `undefined` for an empty chain so React omits the attribute instead
|
|
88
|
+
* of emitting an empty string that consumers would have to special-case.
|
|
89
|
+
*/
|
|
90
|
+
export const dsChainValue = (chain: readonly string[]): string | undefined =>
|
|
91
|
+
chain.length > 0 ? chain.join(DS_CHAIN_SEPARATOR) : undefined;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Resolves the business object governing `element` by walking up the DOM to the
|
|
95
|
+
* nearest ancestor carrying `DS_OBJECT_ATTRIBUTE`, `element` itself included.
|
|
96
|
+
*
|
|
97
|
+
* Nearest wins. A legacy Perl screen tags one layout wrapper, so every element
|
|
98
|
+
* on it resolves to the same object; a React screen tags individual elements,
|
|
99
|
+
* so an interaction resolves to the region it started in rather than to the
|
|
100
|
+
* page. Both fall out of the same walk.
|
|
101
|
+
*
|
|
102
|
+
* Returns `undefined` when no ancestor is tagged — including for an element
|
|
103
|
+
* that is not in the document, and for an empty attribute value — so React
|
|
104
|
+
* omits the attribute instead of emitting an empty string that a consumer would
|
|
105
|
+
* have to special-case. An untagged screen must produce no answer, never a
|
|
106
|
+
* borrowed one.
|
|
107
|
+
*/
|
|
108
|
+
export const dsObjectValue = (
|
|
109
|
+
element: Element | null | undefined,
|
|
110
|
+
): string | undefined =>
|
|
111
|
+
element
|
|
112
|
+
?.closest(`[${DS_OBJECT_ATTRIBUTE}]`)
|
|
113
|
+
?.getAttribute(DS_OBJECT_ATTRIBUTE) || undefined;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attribute name that identifies which design-system component rendered a DOM
|
|
3
|
+
* element. Always lowercase and hyphenated; HTML lowercases attribute names, so
|
|
4
|
+
* a camelCase spelling would silently produce a different attribute.
|
|
5
|
+
*/
|
|
6
|
+
export const DS_COMPONENT_ATTRIBUTE = 'data-ds-component';
|
|
7
|
+
|
|
8
|
+
/** Attribute record applied to a design-system component's root element. */
|
|
9
|
+
export type DsComponentAttribute = {
|
|
10
|
+
'data-ds-component': string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns the `data-ds-component` attribute for a component's root element.
|
|
15
|
+
*
|
|
16
|
+
* Spread the result as the first attribute on the root element so a
|
|
17
|
+
* consumer-supplied `data-ds-component` in the component's rest props still
|
|
18
|
+
* wins. When rest props are forwarded to a nested element instead of the root,
|
|
19
|
+
* pull `data-ds-component` out of the props first and pass it as `override` so
|
|
20
|
+
* the explicit value lands on the root and does not leak onto the inner
|
|
21
|
+
* element.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* // Rest props are spread on the root: ordering handles the override.
|
|
26
|
+
* <Box {...dsComponent('Badge')} className={classes.root} {...otherProps} />
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* // Rest props are forwarded to a nested control: pass the override through.
|
|
32
|
+
* const { 'data-ds-component': dsComponentName, ...rest } = props;
|
|
33
|
+
*
|
|
34
|
+
* <Box {...dsComponent('Checkbox', dsComponentName)}>
|
|
35
|
+
* <Box as="input" {...otherProps} />
|
|
36
|
+
* </Box>;
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export const dsComponent = (
|
|
40
|
+
name: string,
|
|
41
|
+
override?: string,
|
|
42
|
+
): DsComponentAttribute => ({
|
|
43
|
+
[DS_COMPONENT_ATTRIBUTE]: override ?? name,
|
|
44
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attribute name that names an interactive part inside a design-system
|
|
3
|
+
* component. Always lowercase and hyphenated; HTML lowercases attribute names,
|
|
4
|
+
* so a camelCase spelling would silently produce a different attribute.
|
|
5
|
+
*/
|
|
6
|
+
export const DS_PART_ATTRIBUTE = 'data-ds-part';
|
|
7
|
+
|
|
8
|
+
/** Attribute record applied to a named part of a design-system component. */
|
|
9
|
+
export type DsPartAttribute = {
|
|
10
|
+
'data-ds-part': string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns the `data-ds-part` attribute for a named part of a component.
|
|
15
|
+
*
|
|
16
|
+
* Internal instrumentation with the same status as `data-ds-component`: emitted
|
|
17
|
+
* automatically, not a supported public API, and not part of any prop type.
|
|
18
|
+
* **It is not a test handle** — tests query by role, or by the `data-testid` a
|
|
19
|
+
* consumer supplied. Do not document it, type it, or reference it from a test
|
|
20
|
+
* outside this repository.
|
|
21
|
+
*
|
|
22
|
+
* It exists for the collector, which needs to tell apart the interactive parts
|
|
23
|
+
* of one component: a click on a `Select`'s trigger is a different event from a
|
|
24
|
+
* click on a chip's remove control inside it, and both report the same
|
|
25
|
+
* `data-ds-component` and the same chain. The part name is what separates them,
|
|
26
|
+
* and it is the DS's to assign because only the DS knows its own anatomy.
|
|
27
|
+
*
|
|
28
|
+
* Spread the result before the component's rest props so a consumer-supplied
|
|
29
|
+
* value in rest props still wins, matching `dsComponent`.
|
|
30
|
+
*
|
|
31
|
+
* The chain mechanism reads `data-testid` only (see `Box` and
|
|
32
|
+
* `~/utils/dsChain`), so this attribute never contributes a chain node.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <Box role="combobox" {...dsPart('trigger')} {...triggerProps} />
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export const dsPart = (part: string): DsPartAttribute => ({
|
|
40
|
+
[DS_PART_ATTRIBUTE]: part,
|
|
41
|
+
});
|
package/src/utils/splitProps.ts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import { css, cx } from '@styled-system/css';
|
|
2
2
|
import { splitCssProps } from '@styled-system/jsx';
|
|
3
3
|
|
|
4
|
+
/** Record of native attributes and Panda CSS properties accepted by `splitProps`. */
|
|
4
5
|
type PropsRecord = Record<string, unknown>;
|
|
5
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Separates Panda CSS props from remaining element props and returns a merged
|
|
9
|
+
* class name for the generated styles.
|
|
10
|
+
*
|
|
11
|
+
* The first tuple value combines an existing string `className` with styles
|
|
12
|
+
* generated from Panda CSS props, including the `css` prop. The second value
|
|
13
|
+
* excludes those styling props and `className`, so it can be spread onto an
|
|
14
|
+
* element without leaking them to the DOM.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const [className, elementProps] = splitProps({ p: '4', id: 'profile' });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
6
21
|
export const splitProps = (props: PropsRecord): [string, PropsRecord] => {
|
|
7
22
|
const [cssProps, otherProps] = splitCssProps(props);
|
|
8
23
|
const { css: cssProp, ...styleProps } = cssProps;
|