@planningcenter/tapestry 3.6.1-qa-1035.0 → 3.7.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.
- package/dist/components/flex/Flex.d.ts +19 -3
- package/dist/components/flex/Flex.d.ts.map +1 -1
- package/dist/components/flex/Flex.js +5 -3
- package/dist/components/flex/Flex.js.map +1 -1
- package/dist/components/link/BaseLink.d.ts +1 -3
- package/dist/components/link/BaseLink.d.ts.map +1 -1
- package/dist/components/link/BaseLink.js.map +1 -1
- package/dist/components/link/Link.d.ts +2 -1
- package/dist/components/link/Link.d.ts.map +1 -1
- package/dist/components/link/Link.js.map +1 -1
- package/dist/index.css +1536 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/reactRender.css +2996 -2228
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRenderLegacy.css +2996 -2228
- package/dist/reactRenderLegacy.css.map +1 -1
- package/dist/unstable.css +3944 -3176
- package/dist/unstable.css.map +1 -1
- package/dist/unstable.d.ts +0 -1
- package/dist/unstable.d.ts.map +1 -1
- package/dist/unstable.js +1 -1
- package/dist/utilities/containerQuery.d.ts +80 -0
- package/dist/utilities/containerQuery.d.ts.map +1 -0
- package/dist/utilities/containerQuery.js +180 -0
- package/dist/utilities/containerQuery.js.map +1 -0
- package/dist/utilities/cssRegistry.d.ts +20 -0
- package/dist/utilities/cssRegistry.d.ts.map +1 -0
- package/dist/utilities/cssRegistry.js +65 -0
- package/dist/utilities/cssRegistry.js.map +1 -0
- package/dist/utilities/spacingTokens.d.ts +14 -1
- package/dist/utilities/spacingTokens.d.ts.map +1 -1
- package/dist/utilities/spacingTokens.js +18 -0
- package/dist/utilities/spacingTokens.js.map +1 -0
- package/dist/utilities/typeUtils.d.ts +4 -0
- package/dist/utilities/typeUtils.d.ts.map +1 -0
- package/dist/utilities/useContainerClass.d.ts +2 -0
- package/dist/utilities/useContainerClass.d.ts.map +1 -0
- package/dist/utilities/useContainerClass.js +25 -0
- package/dist/utilities/useContainerClass.js.map +1 -0
- package/dist/utilities/useInsertionEffect.d.ts +3 -0
- package/dist/utilities/useInsertionEffect.d.ts.map +1 -0
- package/dist/utilities/useInsertionEffect.js +9 -0
- package/dist/utilities/useInsertionEffect.js.map +1 -0
- package/package.json +5 -5
package/dist/unstable.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { Banner } from "./components/Banner/Banner";
|
|
2
|
-
export * from "./components/flex";
|
|
3
2
|
export * from "./index";
|
|
4
3
|
export { type ReactNativeTokens, reactNativeTokens, } from "@planningcenter/tapestry-tokens/react-native-tokens";
|
|
5
4
|
//# sourceMappingURL=unstable.d.ts.map
|
package/dist/unstable.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unstable.d.ts","sourceRoot":"","sources":["../src/unstable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AACnD,cAAc,
|
|
1
|
+
{"version":3,"file":"unstable.d.ts","sourceRoot":"","sources":["../src/unstable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AACnD,cAAc,SAAS,CAAA;AACvB,OAAO,EACL,KAAK,iBAAiB,EACtB,iBAAiB,GAClB,MAAM,qDAAqD,CAAA"}
|
package/dist/unstable.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { Banner } from './components/Banner/Banner.js';
|
|
2
|
-
export { Flex } from './components/flex/Flex.js';
|
|
3
2
|
import './components/page-header/index.js';
|
|
4
3
|
import './components/sidenav/index.js';
|
|
5
4
|
import './components/checkbox/tds-indeterminate.js';
|
|
@@ -15,6 +14,7 @@ export { ComboBox, ComboBoxItem, ComboBoxSection } from './components/combo-box/
|
|
|
15
14
|
export { DatePicker } from './components/date-picker/DatePicker.js';
|
|
16
15
|
export { Dropdown, DropdownAction, DropdownLink, DropdownMenu, DropdownSection, DropdownSeparator, DropdownTrigger } from './components/dropdown/Dropdown.js';
|
|
17
16
|
export { Field } from './components/field/Field.js';
|
|
17
|
+
export { Flex } from './components/flex/Flex.js';
|
|
18
18
|
export { Input } from './components/input/Input.js';
|
|
19
19
|
export { IconLink } from './components/link/IconLink.js';
|
|
20
20
|
export { Link } from './components/link/Link.js';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container-query support for layout primitives.
|
|
3
|
+
*
|
|
4
|
+
* Parses container-query condition strings, builds the CSS rule bodies, and
|
|
5
|
+
* hashes them for deduplication.
|
|
6
|
+
*
|
|
7
|
+
* Only `inline-size` comparisons are accepted. Named containers are supported:
|
|
8
|
+
*
|
|
9
|
+
* "(inline-size > 480px)" → unnamed container
|
|
10
|
+
* "layout (inline-size >= 640px)" → named container
|
|
11
|
+
*/
|
|
12
|
+
export type ContainerKeyParts = {
|
|
13
|
+
/** The full parenthesized condition, e.g. `(inline-size > 480px)`. */
|
|
14
|
+
condition: string;
|
|
15
|
+
containerName: string | null;
|
|
16
|
+
};
|
|
17
|
+
export type ParsedContainerKey = {
|
|
18
|
+
ok: true;
|
|
19
|
+
value: ContainerKeyParts;
|
|
20
|
+
} | {
|
|
21
|
+
error: string;
|
|
22
|
+
ok: false;
|
|
23
|
+
};
|
|
24
|
+
/** Maps layout prop names to their CSS property names where the two differ. */
|
|
25
|
+
export declare const PROP_TO_CSS_MAP: Record<string, string>;
|
|
26
|
+
/** Props whose values resolve through a spacing token map rather than passing through verbatim. */
|
|
27
|
+
export declare const SPACING_PROPS: ReadonlySet<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Parse a container-query key into its optional name and parenthesized
|
|
30
|
+
* condition. Examples:
|
|
31
|
+
*
|
|
32
|
+
* "(inline-size > 480px)" → { containerName: null, condition: "(inline-size > 480px)" }
|
|
33
|
+
* "layout (inline-size >= 640px)" → { containerName: "layout", condition: "(inline-size >= 640px)" }
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseContainerKey(key: string): ParsedContainerKey;
|
|
36
|
+
export type ContainerCssRule = {
|
|
37
|
+
/** Parenthesized condition, e.g. `(inline-size > 480px)`. */
|
|
38
|
+
condition: string;
|
|
39
|
+
containerName: string | null;
|
|
40
|
+
/**
|
|
41
|
+
* CSS declaration body for this rule — no surrounding braces. Multiple
|
|
42
|
+
* declarations must be separated by `;`. Values are written verbatim, so
|
|
43
|
+
* callers must pre-resolve tokens.
|
|
44
|
+
*/
|
|
45
|
+
declarations: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Build a CSS declarations string from a props object, using `PROP_TO_CSS_MAP`
|
|
49
|
+
* for property names and `SPACING_PROPS` to identify which values need
|
|
50
|
+
* spacing token lookup.
|
|
51
|
+
*/
|
|
52
|
+
export declare function propsToCssDeclarations(props: Record<string, unknown>, propToCssMap: Record<string, string>, spacingProps: ReadonlySet<string>, spacingMap: Record<string | number, string>): string;
|
|
53
|
+
/**
|
|
54
|
+
* Build a container query entry — the scope class, CSS, and hash — for a given
|
|
55
|
+
* container map, or `null` if nothing valid was found.
|
|
56
|
+
*/
|
|
57
|
+
export declare function buildContainerEntry(container: Record<string, object>, propToCssMap: Record<string, string>, spacingProps: ReadonlySet<string>, spacingMap: Record<string | number, string>, onWarn?: (message: string) => void): {
|
|
58
|
+
containerClass: string;
|
|
59
|
+
css: string;
|
|
60
|
+
hash: string;
|
|
61
|
+
} | null;
|
|
62
|
+
/**
|
|
63
|
+
* Build a minified CSS string of one `@container` rule per entry, all
|
|
64
|
+
* selecting the provided scope class. Output is deterministic given identical
|
|
65
|
+
* input — same rule order, no whitespace variation — so the same input always
|
|
66
|
+
* produces the same string.
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildContainerCss(args: {
|
|
69
|
+
containerClass: string;
|
|
70
|
+
rules: ContainerCssRule[];
|
|
71
|
+
}): string;
|
|
72
|
+
/**
|
|
73
|
+
* Stable 32-bit string hash (djb2-xor variant) rendered in base-36.
|
|
74
|
+
*
|
|
75
|
+
* Called on a fingerprint derived from the rules — not the final CSS — so
|
|
76
|
+
* the scope class can be computed before `buildContainerCss` runs. Base-36
|
|
77
|
+
* keeps class names shorter than hex for the same bit width.
|
|
78
|
+
*/
|
|
79
|
+
export declare function hashCss(input: string): string;
|
|
80
|
+
//# sourceMappingURL=containerQuery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"containerQuery.d.ts","sourceRoot":"","sources":["../../src/utilities/containerQuery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,GACtC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,CAAA;AAEhC,+EAA+E;AAC/E,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAalD,CAAA;AAED,mGAAmG;AACnG,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,CAO5C,CAAA;AAKF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CA2CjE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,EACjC,UAAU,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,GAC1C,MAAM,CAoBR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,EACjC,UAAU,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,EAC3C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACjC;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAmC9D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,gBAAgB,EAAE,CAAA;CAC1B,GAAG,MAAM,CAWT;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7C"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container-query support for layout primitives.
|
|
3
|
+
*
|
|
4
|
+
* Parses container-query condition strings, builds the CSS rule bodies, and
|
|
5
|
+
* hashes them for deduplication.
|
|
6
|
+
*
|
|
7
|
+
* Only `inline-size` comparisons are accepted. Named containers are supported:
|
|
8
|
+
*
|
|
9
|
+
* "(inline-size > 480px)" → unnamed container
|
|
10
|
+
* "layout (inline-size >= 640px)" → named container
|
|
11
|
+
*/
|
|
12
|
+
/** Maps layout prop names to their CSS property names where the two differ. */
|
|
13
|
+
const PROP_TO_CSS_MAP = {
|
|
14
|
+
align: "align-items",
|
|
15
|
+
alignSelf: "align-self",
|
|
16
|
+
basis: "flex-basis",
|
|
17
|
+
columnGap: "column-gap",
|
|
18
|
+
direction: "flex-direction",
|
|
19
|
+
grow: "flex-grow",
|
|
20
|
+
justify: "justify-content",
|
|
21
|
+
paddingBlock: "padding-block",
|
|
22
|
+
paddingInline: "padding-inline",
|
|
23
|
+
rowGap: "row-gap",
|
|
24
|
+
shrink: "flex-shrink",
|
|
25
|
+
wrap: "flex-wrap",
|
|
26
|
+
};
|
|
27
|
+
/** Props whose values resolve through a spacing token map rather than passing through verbatim. */
|
|
28
|
+
const SPACING_PROPS = new Set([
|
|
29
|
+
"columnGap",
|
|
30
|
+
"gap",
|
|
31
|
+
"padding",
|
|
32
|
+
"paddingBlock",
|
|
33
|
+
"paddingInline",
|
|
34
|
+
"rowGap",
|
|
35
|
+
]);
|
|
36
|
+
const NAME_PATTERN = /^[A-Za-z_][\w-]*$/;
|
|
37
|
+
const INNER_CONDITION_PATTERN = /^inline-size\s*(?:<=|>=|<|>)\s*\S+$/;
|
|
38
|
+
/**
|
|
39
|
+
* Parse a container-query key into its optional name and parenthesized
|
|
40
|
+
* condition. Examples:
|
|
41
|
+
*
|
|
42
|
+
* "(inline-size > 480px)" → { containerName: null, condition: "(inline-size > 480px)" }
|
|
43
|
+
* "layout (inline-size >= 640px)" → { containerName: "layout", condition: "(inline-size >= 640px)" }
|
|
44
|
+
*/
|
|
45
|
+
function parseContainerKey(key) {
|
|
46
|
+
const trimmed = key.trim();
|
|
47
|
+
if (trimmed.length === 0) {
|
|
48
|
+
return { error: "empty key", ok: false };
|
|
49
|
+
}
|
|
50
|
+
const lparen = trimmed.indexOf("(");
|
|
51
|
+
if (lparen === -1) {
|
|
52
|
+
return { error: `missing '(' in "${key}"`, ok: false };
|
|
53
|
+
}
|
|
54
|
+
const namePart = trimmed.slice(0, lparen).trim();
|
|
55
|
+
const conditionPart = trimmed.slice(lparen);
|
|
56
|
+
if (!conditionPart.startsWith("(") ||
|
|
57
|
+
!conditionPart.endsWith(")") ||
|
|
58
|
+
conditionPart.indexOf("(", 1) !== -1 ||
|
|
59
|
+
conditionPart.indexOf(")") !== conditionPart.length - 1) {
|
|
60
|
+
return {
|
|
61
|
+
error: `expected a single balanced "(...)" in "${key}"`,
|
|
62
|
+
ok: false,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const inner = conditionPart.slice(1, -1).trim();
|
|
66
|
+
if (!INNER_CONDITION_PATTERN.test(inner)) {
|
|
67
|
+
return {
|
|
68
|
+
error: `unsupported condition "${inner}" — only "inline-size <op> <value>" is allowed`,
|
|
69
|
+
ok: false,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
let containerName = null;
|
|
73
|
+
if (namePart.length > 0) {
|
|
74
|
+
if (!NAME_PATTERN.test(namePart)) {
|
|
75
|
+
return { error: `invalid container name "${namePart}"`, ok: false };
|
|
76
|
+
}
|
|
77
|
+
containerName = namePart;
|
|
78
|
+
}
|
|
79
|
+
return { ok: true, value: { condition: conditionPart, containerName } };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build a CSS declarations string from a props object, using `PROP_TO_CSS_MAP`
|
|
83
|
+
* for property names and `SPACING_PROPS` to identify which values need
|
|
84
|
+
* spacing token lookup.
|
|
85
|
+
*/
|
|
86
|
+
function propsToCssDeclarations(props, propToCssMap, spacingProps, spacingMap) {
|
|
87
|
+
let out = "";
|
|
88
|
+
for (const [prop, cssProperty] of Object.entries(propToCssMap)) {
|
|
89
|
+
const value = props[prop];
|
|
90
|
+
if (value === undefined)
|
|
91
|
+
continue;
|
|
92
|
+
if (spacingProps.has(prop)) {
|
|
93
|
+
const token = spacingMap[value];
|
|
94
|
+
if (token !== undefined)
|
|
95
|
+
out += `${cssProperty}:${token};`;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
out += `${cssProperty}:${value};`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
for (const prop of spacingProps) {
|
|
102
|
+
if (prop in propToCssMap)
|
|
103
|
+
continue;
|
|
104
|
+
const value = props[prop];
|
|
105
|
+
if (value === undefined)
|
|
106
|
+
continue;
|
|
107
|
+
const token = spacingMap[value];
|
|
108
|
+
if (token !== undefined)
|
|
109
|
+
out += `${prop}:${token};`;
|
|
110
|
+
}
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Build a container query entry — the scope class, CSS, and hash — for a given
|
|
115
|
+
* container map, or `null` if nothing valid was found.
|
|
116
|
+
*/
|
|
117
|
+
function buildContainerEntry(container, propToCssMap, spacingProps, spacingMap, onWarn) {
|
|
118
|
+
const rules = [];
|
|
119
|
+
for (const [key, props] of Object.entries(container)) {
|
|
120
|
+
const parsed = parseContainerKey(key);
|
|
121
|
+
if (!parsed.ok) {
|
|
122
|
+
onWarn?.(`ignoring container query — ${parsed.error}`);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const declarations = propsToCssDeclarations(props, propToCssMap, spacingProps, spacingMap);
|
|
126
|
+
if (declarations === "")
|
|
127
|
+
continue;
|
|
128
|
+
rules.push({
|
|
129
|
+
condition: parsed.value.condition,
|
|
130
|
+
containerName: parsed.value.containerName,
|
|
131
|
+
declarations,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (rules.length === 0)
|
|
135
|
+
return null;
|
|
136
|
+
const fingerprint = rules
|
|
137
|
+
.map((r) => `${r.containerName ?? ""}|${r.condition}|${r.declarations}`)
|
|
138
|
+
.join(";");
|
|
139
|
+
const hash = hashCss(fingerprint);
|
|
140
|
+
const containerClass = `tds--cq-${hash}`;
|
|
141
|
+
return {
|
|
142
|
+
containerClass,
|
|
143
|
+
css: buildContainerCss({ containerClass, rules }),
|
|
144
|
+
hash,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Build a minified CSS string of one `@container` rule per entry, all
|
|
149
|
+
* selecting the provided scope class. Output is deterministic given identical
|
|
150
|
+
* input — same rule order, no whitespace variation — so the same input always
|
|
151
|
+
* produces the same string.
|
|
152
|
+
*/
|
|
153
|
+
function buildContainerCss(args) {
|
|
154
|
+
const { rules, containerClass } = args;
|
|
155
|
+
return rules
|
|
156
|
+
.map((rule) => {
|
|
157
|
+
const at = rule.containerName === null
|
|
158
|
+
? `@container ${rule.condition}`
|
|
159
|
+
: `@container ${rule.containerName} ${rule.condition}`;
|
|
160
|
+
return `.${containerClass}{${at}{${rule.declarations}}}`;
|
|
161
|
+
})
|
|
162
|
+
.join("");
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Stable 32-bit string hash (djb2-xor variant) rendered in base-36.
|
|
166
|
+
*
|
|
167
|
+
* Called on a fingerprint derived from the rules — not the final CSS — so
|
|
168
|
+
* the scope class can be computed before `buildContainerCss` runs. Base-36
|
|
169
|
+
* keeps class names shorter than hex for the same bit width.
|
|
170
|
+
*/
|
|
171
|
+
function hashCss(input) {
|
|
172
|
+
let h = 5381;
|
|
173
|
+
for (let i = 0; i < input.length; i++) {
|
|
174
|
+
h = (((h << 5) + h) ^ input.charCodeAt(i)) >>> 0;
|
|
175
|
+
}
|
|
176
|
+
return h.toString(36);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export { PROP_TO_CSS_MAP, SPACING_PROPS, buildContainerCss, buildContainerEntry, hashCss, parseContainerKey, propsToCssDeclarations };
|
|
180
|
+
//# sourceMappingURL=containerQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"containerQuery.js","sources":["../../src/utilities/containerQuery.ts"],"sourcesContent":["/**\n * Container-query support for layout primitives.\n *\n * Parses container-query condition strings, builds the CSS rule bodies, and\n * hashes them for deduplication.\n *\n * Only `inline-size` comparisons are accepted. Named containers are supported:\n *\n * \"(inline-size > 480px)\" → unnamed container\n * \"layout (inline-size >= 640px)\" → named container\n */\n\nexport type ContainerKeyParts = {\n /** The full parenthesized condition, e.g. `(inline-size > 480px)`. */\n condition: string\n containerName: string | null\n}\n\nexport type ParsedContainerKey =\n | { ok: true; value: ContainerKeyParts }\n | { error: string; ok: false }\n\n/** Maps layout prop names to their CSS property names where the two differ. */\nexport const PROP_TO_CSS_MAP: Record<string, string> = {\n align: \"align-items\",\n alignSelf: \"align-self\",\n basis: \"flex-basis\",\n columnGap: \"column-gap\",\n direction: \"flex-direction\",\n grow: \"flex-grow\",\n justify: \"justify-content\",\n paddingBlock: \"padding-block\",\n paddingInline: \"padding-inline\",\n rowGap: \"row-gap\",\n shrink: \"flex-shrink\",\n wrap: \"flex-wrap\",\n}\n\n/** Props whose values resolve through a spacing token map rather than passing through verbatim. */\nexport const SPACING_PROPS: ReadonlySet<string> = new Set([\n \"columnGap\",\n \"gap\",\n \"padding\",\n \"paddingBlock\",\n \"paddingInline\",\n \"rowGap\",\n])\n\nconst NAME_PATTERN = /^[A-Za-z_][\\w-]*$/\nconst INNER_CONDITION_PATTERN = /^inline-size\\s*(?:<=|>=|<|>)\\s*\\S+$/\n\n/**\n * Parse a container-query key into its optional name and parenthesized\n * condition. Examples:\n *\n * \"(inline-size > 480px)\" → { containerName: null, condition: \"(inline-size > 480px)\" }\n * \"layout (inline-size >= 640px)\" → { containerName: \"layout\", condition: \"(inline-size >= 640px)\" }\n */\nexport function parseContainerKey(key: string): ParsedContainerKey {\n const trimmed = key.trim()\n if (trimmed.length === 0) {\n return { error: \"empty key\", ok: false }\n }\n\n const lparen = trimmed.indexOf(\"(\")\n if (lparen === -1) {\n return { error: `missing '(' in \"${key}\"`, ok: false }\n }\n\n const namePart = trimmed.slice(0, lparen).trim()\n const conditionPart = trimmed.slice(lparen)\n\n if (\n !conditionPart.startsWith(\"(\") ||\n !conditionPart.endsWith(\")\") ||\n conditionPart.indexOf(\"(\", 1) !== -1 ||\n conditionPart.indexOf(\")\") !== conditionPart.length - 1\n ) {\n return {\n error: `expected a single balanced \"(...)\" in \"${key}\"`,\n ok: false,\n }\n }\n\n const inner = conditionPart.slice(1, -1).trim()\n if (!INNER_CONDITION_PATTERN.test(inner)) {\n return {\n error: `unsupported condition \"${inner}\" — only \"inline-size <op> <value>\" is allowed`,\n ok: false,\n }\n }\n\n let containerName: string | null = null\n if (namePart.length > 0) {\n if (!NAME_PATTERN.test(namePart)) {\n return { error: `invalid container name \"${namePart}\"`, ok: false }\n }\n containerName = namePart\n }\n\n return { ok: true, value: { condition: conditionPart, containerName } }\n}\n\nexport type ContainerCssRule = {\n /** Parenthesized condition, e.g. `(inline-size > 480px)`. */\n condition: string\n containerName: string | null\n /**\n * CSS declaration body for this rule — no surrounding braces. Multiple\n * declarations must be separated by `;`. Values are written verbatim, so\n * callers must pre-resolve tokens.\n */\n declarations: string\n}\n\n/**\n * Build a CSS declarations string from a props object, using `PROP_TO_CSS_MAP`\n * for property names and `SPACING_PROPS` to identify which values need\n * spacing token lookup.\n */\nexport function propsToCssDeclarations(\n props: Record<string, unknown>,\n propToCssMap: Record<string, string>,\n spacingProps: ReadonlySet<string>,\n spacingMap: Record<string | number, string>\n): string {\n let out = \"\"\n for (const [prop, cssProperty] of Object.entries(propToCssMap)) {\n const value = props[prop]\n if (value === undefined) continue\n if (spacingProps.has(prop)) {\n const token = spacingMap[value as string | number]\n if (token !== undefined) out += `${cssProperty}:${token};`\n } else {\n out += `${cssProperty}:${value};`\n }\n }\n for (const prop of spacingProps) {\n if (prop in propToCssMap) continue\n const value = props[prop]\n if (value === undefined) continue\n const token = spacingMap[value as string | number]\n if (token !== undefined) out += `${prop}:${token};`\n }\n return out\n}\n\n/**\n * Build a container query entry — the scope class, CSS, and hash — for a given\n * container map, or `null` if nothing valid was found.\n */\nexport function buildContainerEntry(\n container: Record<string, object>,\n propToCssMap: Record<string, string>,\n spacingProps: ReadonlySet<string>,\n spacingMap: Record<string | number, string>,\n onWarn?: (message: string) => void\n): { containerClass: string; css: string; hash: string } | null {\n const rules: ContainerCssRule[] = []\n\n for (const [key, props] of Object.entries(container)) {\n const parsed = parseContainerKey(key)\n if (!parsed.ok) {\n onWarn?.(`ignoring container query — ${parsed.error}`)\n continue\n }\n const declarations = propsToCssDeclarations(\n props as Record<string, unknown>,\n propToCssMap,\n spacingProps,\n spacingMap\n )\n if (declarations === \"\") continue\n rules.push({\n condition: parsed.value.condition,\n containerName: parsed.value.containerName,\n declarations,\n })\n }\n\n if (rules.length === 0) return null\n\n const fingerprint = rules\n .map((r) => `${r.containerName ?? \"\"}|${r.condition}|${r.declarations}`)\n .join(\";\")\n const hash = hashCss(fingerprint)\n const containerClass = `tds--cq-${hash}`\n return {\n containerClass,\n css: buildContainerCss({ containerClass, rules }),\n hash,\n }\n}\n\n/**\n * Build a minified CSS string of one `@container` rule per entry, all\n * selecting the provided scope class. Output is deterministic given identical\n * input — same rule order, no whitespace variation — so the same input always\n * produces the same string.\n */\nexport function buildContainerCss(args: {\n containerClass: string\n rules: ContainerCssRule[]\n}): string {\n const { rules, containerClass } = args\n return rules\n .map((rule) => {\n const at =\n rule.containerName === null\n ? `@container ${rule.condition}`\n : `@container ${rule.containerName} ${rule.condition}`\n return `.${containerClass}{${at}{${rule.declarations}}}`\n })\n .join(\"\")\n}\n\n/**\n * Stable 32-bit string hash (djb2-xor variant) rendered in base-36.\n *\n * Called on a fingerprint derived from the rules — not the final CSS — so\n * the scope class can be computed before `buildContainerCss` runs. Base-36\n * keeps class names shorter than hex for the same bit width.\n */\nexport function hashCss(input: string): string {\n let h = 5381\n for (let i = 0; i < input.length; i++) {\n h = (((h << 5) + h) ^ input.charCodeAt(i)) >>> 0\n }\n return h.toString(36)\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny registry for runtime-injected CSS.
|
|
3
|
+
*
|
|
4
|
+
* Used by layout primitives that emit container-query rules. Rather than
|
|
5
|
+
* render an inline `<style>` per component instance, `registerStyle` appends
|
|
6
|
+
* a single stylesheet to the document per unique content hash and
|
|
7
|
+
* short-circuits on subsequent calls.
|
|
8
|
+
*
|
|
9
|
+
* Primary path: Constructable Stylesheets (`new CSSStyleSheet()` +
|
|
10
|
+
* `document.adoptedStyleSheets`) — no DOM nodes, single parse, Shadow DOM
|
|
11
|
+
* compatible. Falls back to `<style>` elements in environments that don't
|
|
12
|
+
* support Constructable Stylesheets (e.g. jsdom).
|
|
13
|
+
*
|
|
14
|
+
* No-ops on the server (`typeof document === "undefined"`).
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerStyle(hash: string, css: string): void;
|
|
17
|
+
export declare function unregisterStyle(hash: string): void;
|
|
18
|
+
/** For test isolation only — clears the internal sheet registry. */
|
|
19
|
+
export declare function _resetForTest(): void;
|
|
20
|
+
//# sourceMappingURL=cssRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cssRegistry.d.ts","sourceRoot":"","sources":["../../src/utilities/cssRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CA0B7D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkBlD;AAED,oEAAoE;AACpE,wBAAgB,aAAa,IAAI,IAAI,CAGpC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny registry for runtime-injected CSS.
|
|
3
|
+
*
|
|
4
|
+
* Used by layout primitives that emit container-query rules. Rather than
|
|
5
|
+
* render an inline `<style>` per component instance, `registerStyle` appends
|
|
6
|
+
* a single stylesheet to the document per unique content hash and
|
|
7
|
+
* short-circuits on subsequent calls.
|
|
8
|
+
*
|
|
9
|
+
* Primary path: Constructable Stylesheets (`new CSSStyleSheet()` +
|
|
10
|
+
* `document.adoptedStyleSheets`) — no DOM nodes, single parse, Shadow DOM
|
|
11
|
+
* compatible. Falls back to `<style>` elements in environments that don't
|
|
12
|
+
* support Constructable Stylesheets (e.g. jsdom).
|
|
13
|
+
*
|
|
14
|
+
* No-ops on the server (`typeof document === "undefined"`).
|
|
15
|
+
*/
|
|
16
|
+
const sheets = new Map();
|
|
17
|
+
const refCounts = new Map();
|
|
18
|
+
function registerStyle(hash, css) {
|
|
19
|
+
if (typeof document === "undefined")
|
|
20
|
+
return;
|
|
21
|
+
refCounts.set(hash, (refCounts.get(hash) ?? 0) + 1);
|
|
22
|
+
if (sheets.has(hash))
|
|
23
|
+
return;
|
|
24
|
+
// Check if Constructable Stylesheets are not supported (e.g. jsdom)
|
|
25
|
+
const needsStyleElementFallback = typeof CSSStyleSheet === "undefined" ||
|
|
26
|
+
!("replaceSync" in CSSStyleSheet.prototype);
|
|
27
|
+
if (needsStyleElementFallback) {
|
|
28
|
+
const id = `tds--cq-${hash}`;
|
|
29
|
+
if (document.getElementById(id) !== null)
|
|
30
|
+
return;
|
|
31
|
+
const el = document.createElement("style");
|
|
32
|
+
el.id = id;
|
|
33
|
+
el.textContent = css;
|
|
34
|
+
document.head.appendChild(el);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const sheet = new CSSStyleSheet();
|
|
38
|
+
sheet.replaceSync(css);
|
|
39
|
+
sheets.set(hash, sheet);
|
|
40
|
+
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
|
|
41
|
+
}
|
|
42
|
+
function unregisterStyle(hash) {
|
|
43
|
+
if (typeof document === "undefined")
|
|
44
|
+
return;
|
|
45
|
+
const count = refCounts.get(hash);
|
|
46
|
+
if (count === undefined)
|
|
47
|
+
return;
|
|
48
|
+
if (count <= 1) {
|
|
49
|
+
refCounts.delete(hash);
|
|
50
|
+
const sheet = sheets.get(hash);
|
|
51
|
+
if (sheet) {
|
|
52
|
+
document.adoptedStyleSheets = document.adoptedStyleSheets.filter((s) => s !== sheet);
|
|
53
|
+
sheets.delete(hash);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
document.getElementById(`tds--cq-${hash}`)?.remove();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
refCounts.set(hash, count - 1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { registerStyle, unregisterStyle };
|
|
65
|
+
//# sourceMappingURL=cssRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cssRegistry.js","sources":["../../src/utilities/cssRegistry.ts"],"sourcesContent":["/**\n * Tiny registry for runtime-injected CSS.\n *\n * Used by layout primitives that emit container-query rules. Rather than\n * render an inline `<style>` per component instance, `registerStyle` appends\n * a single stylesheet to the document per unique content hash and\n * short-circuits on subsequent calls.\n *\n * Primary path: Constructable Stylesheets (`new CSSStyleSheet()` +\n * `document.adoptedStyleSheets`) — no DOM nodes, single parse, Shadow DOM\n * compatible. Falls back to `<style>` elements in environments that don't\n * support Constructable Stylesheets (e.g. jsdom).\n *\n * No-ops on the server (`typeof document === \"undefined\"`).\n */\n\nconst sheets = new Map<string, CSSStyleSheet>()\nconst refCounts = new Map<string, number>()\n\nexport function registerStyle(hash: string, css: string): void {\n if (typeof document === \"undefined\") return\n\n refCounts.set(hash, (refCounts.get(hash) ?? 0) + 1)\n\n if (sheets.has(hash)) return\n\n // Check if Constructable Stylesheets are not supported (e.g. jsdom)\n const needsStyleElementFallback =\n typeof CSSStyleSheet === \"undefined\" ||\n !(\"replaceSync\" in CSSStyleSheet.prototype)\n\n if (needsStyleElementFallback) {\n const id = `tds--cq-${hash}`\n if (document.getElementById(id) !== null) return\n const el = document.createElement(\"style\")\n el.id = id\n el.textContent = css\n document.head.appendChild(el)\n return\n }\n\n const sheet = new CSSStyleSheet()\n sheet.replaceSync(css)\n sheets.set(hash, sheet)\n document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]\n}\n\nexport function unregisterStyle(hash: string): void {\n if (typeof document === \"undefined\") return\n const count = refCounts.get(hash)\n if (count === undefined) return\n if (count <= 1) {\n refCounts.delete(hash)\n const sheet = sheets.get(hash)\n if (sheet) {\n document.adoptedStyleSheets = document.adoptedStyleSheets.filter(\n (s) => s !== sheet\n )\n sheets.delete(hash)\n } else {\n document.getElementById(`tds--cq-${hash}`)?.remove()\n }\n } else {\n refCounts.set(hash, count - 1)\n }\n}\n\n/** For test isolation only — clears the internal sheet registry. */\nexport function _resetForTest(): void {\n sheets.clear()\n refCounts.clear()\n}\n"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;AAcG;AAEH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB;AAC/C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB;AAErC,SAAU,aAAa,CAAC,IAAY,EAAE,GAAW,EAAA;IACrD,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE;AAErC,IAAA,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEnD,IAAA,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE;;AAGtB,IAAA,MAAM,yBAAyB,GAC7B,OAAO,aAAa,KAAK,WAAW;AACpC,QAAA,EAAE,aAAa,IAAI,aAAa,CAAC,SAAS,CAAC;IAE7C,IAAI,yBAAyB,EAAE;AAC7B,QAAA,MAAM,EAAE,GAAG,CAAA,QAAA,EAAW,IAAI,EAAE;AAC5B,QAAA,IAAI,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,IAAI;YAAE;QAC1C,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC1C,QAAA,EAAE,CAAC,EAAE,GAAG,EAAE;AACV,QAAA,EAAE,CAAC,WAAW,GAAG,GAAG;AACpB,QAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B;IACF;AAEA,IAAA,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE;AACjC,IAAA,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC;AACtB,IAAA,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,kBAAkB,GAAG,CAAC,GAAG,QAAQ,CAAC,kBAAkB,EAAE,KAAK,CAAC;AACvE;AAEM,SAAU,eAAe,CAAC,IAAY,EAAA;IAC1C,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE;IACrC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE;AACzB,IAAA,IAAI,KAAK,IAAI,CAAC,EAAE;AACd,QAAA,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QAC9B,IAAI,KAAK,EAAE;AACT,YAAA,QAAQ,CAAC,kBAAkB,GAAG,QAAQ,CAAC,kBAAkB,CAAC,MAAM,CAC9D,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,CACnB;AACD,YAAA,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;QACrB;aAAO;YACL,QAAQ,CAAC,cAAc,CAAC,CAAA,QAAA,EAAW,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE;QACtD;IACF;SAAO;QACL,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC;IAChC;AACF;;;;"}
|
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const SPACING_MAP: {
|
|
2
|
+
readonly 0: "0";
|
|
3
|
+
readonly 0.25: "var(--t-spacing-fourth)";
|
|
4
|
+
readonly 0.5: "var(--t-spacing-half)";
|
|
5
|
+
readonly 1: "var(--t-spacing-1)";
|
|
6
|
+
readonly 1.5: "var(--t-spacing-1-half)";
|
|
7
|
+
readonly 2: "var(--t-spacing-2)";
|
|
8
|
+
readonly 3: "var(--t-spacing-3)";
|
|
9
|
+
readonly 4: "var(--t-spacing-4)";
|
|
10
|
+
readonly 5: "var(--t-spacing-5)";
|
|
11
|
+
readonly 6: "var(--t-spacing-6)";
|
|
12
|
+
readonly 7: "var(--t-spacing-7)";
|
|
13
|
+
};
|
|
14
|
+
export type Spacing = keyof typeof SPACING_MAP;
|
|
2
15
|
//# sourceMappingURL=spacingTokens.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spacingTokens.d.ts","sourceRoot":"","sources":["../../src/utilities/spacingTokens.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"spacingTokens.d.ts","sourceRoot":"","sources":["../../src/utilities/spacingTokens.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW;;;;;;;;;;;;CAcd,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,WAAW,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const SPACING_MAP = {
|
|
2
|
+
0: "0",
|
|
3
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
4
|
+
0.25: "var(--t-spacing-fourth)",
|
|
5
|
+
0.5: "var(--t-spacing-half)",
|
|
6
|
+
/* eslint-enable sort-keys-fix/sort-keys-fix */
|
|
7
|
+
1: "var(--t-spacing-1)",
|
|
8
|
+
1.5: "var(--t-spacing-1-half)",
|
|
9
|
+
2: "var(--t-spacing-2)",
|
|
10
|
+
3: "var(--t-spacing-3)",
|
|
11
|
+
4: "var(--t-spacing-4)",
|
|
12
|
+
5: "var(--t-spacing-5)",
|
|
13
|
+
6: "var(--t-spacing-6)",
|
|
14
|
+
7: "var(--t-spacing-7)",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { SPACING_MAP };
|
|
18
|
+
//# sourceMappingURL=spacingTokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spacingTokens.js","sources":["../../src/utilities/spacingTokens.ts"],"sourcesContent":["export const SPACING_MAP = {\n 0: \"0\",\n /* eslint-disable sort-keys-fix/sort-keys-fix */\n 0.25: \"var(--t-spacing-fourth)\",\n 0.5: \"var(--t-spacing-half)\",\n /* eslint-enable sort-keys-fix/sort-keys-fix */\n 1: \"var(--t-spacing-1)\",\n 1.5: \"var(--t-spacing-1-half)\",\n 2: \"var(--t-spacing-2)\",\n 3: \"var(--t-spacing-3)\",\n 4: \"var(--t-spacing-4)\",\n 5: \"var(--t-spacing-5)\",\n 6: \"var(--t-spacing-6)\",\n 7: \"var(--t-spacing-7)\",\n} as const\n\nexport type Spacing = keyof typeof SPACING_MAP\n"],"names":[],"mappings":"AAAO,MAAM,WAAW,GAAG;AACzB,IAAA,CAAC,EAAE,GAAG;;AAEN,IAAA,IAAI,EAAE,yBAAyB;AAC/B,IAAA,GAAG,EAAE,uBAAuB;;AAE5B,IAAA,CAAC,EAAE,oBAAoB;AACvB,IAAA,GAAG,EAAE,yBAAyB;AAC9B,IAAA,CAAC,EAAE,oBAAoB;AACvB,IAAA,CAAC,EAAE,oBAAoB;AACvB,IAAA,CAAC,EAAE,oBAAoB;AACvB,IAAA,CAAC,EAAE,oBAAoB;AACvB,IAAA,CAAC,EAAE,oBAAoB;AACvB,IAAA,CAAC,EAAE,oBAAoB;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typeUtils.d.ts","sourceRoot":"","sources":["../../src/utilities/typeUtils.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useContainerClass.d.ts","sourceRoot":"","sources":["../../src/utilities/useContainerClass.ts"],"names":[],"mappings":"AASA,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAC5C,MAAM,GAAG,IAAI,CAqBf"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { buildContainerEntry, SPACING_PROPS, PROP_TO_CSS_MAP } from './containerQuery.js';
|
|
2
|
+
import { registerStyle, unregisterStyle } from './cssRegistry.js';
|
|
3
|
+
import { SPACING_MAP } from './spacingTokens.js';
|
|
4
|
+
import { useInsertionEffect } from './useInsertionEffect.js';
|
|
5
|
+
|
|
6
|
+
function useContainerClass(container) {
|
|
7
|
+
const warnings = [];
|
|
8
|
+
const entry = container
|
|
9
|
+
? buildContainerEntry(container, PROP_TO_CSS_MAP, SPACING_PROPS, SPACING_MAP, (msg) => warnings.push(msg))
|
|
10
|
+
: null;
|
|
11
|
+
useInsertionEffect(() => {
|
|
12
|
+
if (entry?.hash && entry?.css)
|
|
13
|
+
registerStyle(entry.hash, entry.css);
|
|
14
|
+
for (const w of warnings)
|
|
15
|
+
console.warn(w);
|
|
16
|
+
return () => {
|
|
17
|
+
if (entry?.hash && entry?.css)
|
|
18
|
+
unregisterStyle(entry.hash);
|
|
19
|
+
};
|
|
20
|
+
}, [entry?.hash, entry?.css]);
|
|
21
|
+
return entry?.containerClass ?? null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { useContainerClass };
|
|
25
|
+
//# sourceMappingURL=useContainerClass.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useContainerClass.js","sources":["../../src/utilities/useContainerClass.ts"],"sourcesContent":["import {\n buildContainerEntry,\n PROP_TO_CSS_MAP,\n SPACING_PROPS,\n} from \"@utilities/containerQuery\"\nimport { registerStyle, unregisterStyle } from \"@utilities/cssRegistry\"\nimport { SPACING_MAP } from \"@utilities/spacingTokens\"\nimport { useInsertionEffect } from \"@utilities/useInsertionEffect\"\n\nexport function useContainerClass(\n container: Record<string, object> | undefined\n): string | null {\n const warnings: string[] = []\n const entry = container\n ? buildContainerEntry(\n container,\n PROP_TO_CSS_MAP,\n SPACING_PROPS,\n SPACING_MAP,\n (msg) => warnings.push(msg)\n )\n : null\n\n useInsertionEffect(() => {\n if (entry?.hash && entry?.css) registerStyle(entry.hash, entry.css)\n for (const w of warnings) console.warn(w)\n return () => {\n if (entry?.hash && entry?.css) unregisterStyle(entry.hash)\n }\n }, [entry?.hash, entry?.css])\n\n return entry?.containerClass ?? null\n}\n"],"names":[],"mappings":";;;;;AASM,SAAU,iBAAiB,CAC/B,SAA6C,EAAA;IAE7C,MAAM,QAAQ,GAAa,EAAE;IAC7B,MAAM,KAAK,GAAG;UACV,mBAAmB,CACjB,SAAS,EACT,eAAe,EACf,aAAa,EACb,WAAW,EACX,CAAC,GAAG,KAAK,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;UAE7B,IAAI;IAER,kBAAkB,CAAC,MAAK;AACtB,QAAA,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,EAAE,GAAG;YAAE,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;QACnE,KAAK,MAAM,CAAC,IAAI,QAAQ;AAAE,YAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACzC,QAAA,OAAO,MAAK;AACV,YAAA,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,EAAE,GAAG;AAAE,gBAAA,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC;AAC5D,QAAA,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAE7B,IAAA,OAAO,KAAK,EAAE,cAAc,IAAI,IAAI;AACtC;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInsertionEffect.d.ts","sourceRoot":"","sources":["../../src/utilities/useInsertionEffect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,eAAO,MAAM,kBAAkB,EACH,OAAO,KAAK,CAAC,eAAe,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
// TODO: Remove this file and import useInsertionEffect directly from "react"
|
|
4
|
+
// once all codebases are off React 17
|
|
5
|
+
const useInsertionEffect = (React__default.useInsertionEffect ??
|
|
6
|
+
React__default.useLayoutEffect);
|
|
7
|
+
|
|
8
|
+
export { useInsertionEffect };
|
|
9
|
+
//# sourceMappingURL=useInsertionEffect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInsertionEffect.js","sources":["../../src/utilities/useInsertionEffect.ts"],"sourcesContent":["// TODO: Remove this file and import useInsertionEffect directly from \"react\"\n// once all codebases are off React 17\nimport React from \"react\"\n\nexport const useInsertionEffect = (React.useInsertionEffect ??\n React.useLayoutEffect) as typeof React.useLayoutEffect\n"],"names":["React"],"mappings":";;AAAA;AACA;AAGO,MAAM,kBAAkB,IAAIA,cAAK,CAAC,kBAAkB;IACzDA,cAAK,CAAC,eAAe;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/tapestry",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"types": "./dist/index.d.ts",
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@planningcenter/tapestry-render": "^3.
|
|
56
|
+
"@planningcenter/tapestry-render": "^3.4.1",
|
|
57
57
|
"@rollup/plugin-commonjs": "^26.0.1",
|
|
58
58
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
59
59
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"shadow-dom-testing-library": "^1.11.3",
|
|
106
106
|
"storybook": "9.1.19",
|
|
107
107
|
"style-dictionary": "^4.2.0",
|
|
108
|
-
"tapestry-wc": "^3.
|
|
108
|
+
"tapestry-wc": "^3.3.0",
|
|
109
109
|
"tsc-alias": "^1.8.16",
|
|
110
110
|
"tsx": "^4.20.5",
|
|
111
111
|
"typescript": "^5.8.3",
|
|
@@ -115,11 +115,11 @@
|
|
|
115
115
|
},
|
|
116
116
|
"dependencies": {
|
|
117
117
|
"@planningcenter/icons": "^15.29.0",
|
|
118
|
-
"@planningcenter/tapestry-tokens": "^3.
|
|
118
|
+
"@planningcenter/tapestry-tokens": "^3.4.1",
|
|
119
119
|
"@radix-ui/react-slot": "^1.3.0",
|
|
120
120
|
"classnames": "^2.5.1",
|
|
121
121
|
"lodash": "^4.17.21",
|
|
122
122
|
"react-aria-components": "^1.17.0"
|
|
123
123
|
},
|
|
124
|
-
"gitHead": "
|
|
124
|
+
"gitHead": "d959b05c0d33fcee1f86953c994ffdff835e3b49"
|
|
125
125
|
}
|