@tenphi/renderer 0.20.4 → 0.21.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 (44) hide show
  1. package/README.md +2 -2
  2. package/dist/client/navigation.js +2 -6
  3. package/dist/client/navigation.js.map +1 -1
  4. package/dist/client/popover-motion.d.ts +6 -0
  5. package/dist/client/popover-motion.d.ts.map +1 -0
  6. package/dist/client/popover-motion.js +14 -0
  7. package/dist/client/popover-motion.js.map +1 -0
  8. package/dist/client/search.js +55 -14
  9. package/dist/client/search.js.map +1 -1
  10. package/dist/components/GlobalStyles.js +97 -48
  11. package/dist/components/HeaderLinks.astro +14 -3
  12. package/dist/components/Icon.astro +1 -1
  13. package/dist/components/LayoutComponents.js +31 -40
  14. package/dist/components/Preview.astro +1 -1
  15. package/dist/components/SelectPopover.astro +64 -0
  16. package/dist/components/TastyComponents.js +16 -2
  17. package/dist/components/VersionSwitcher.astro +11 -18
  18. package/dist/components/component-styles.test.ts +4 -20
  19. package/dist/components/component-styles.ts +2 -22
  20. package/dist/components/select-popover-styles.js +107 -0
  21. package/dist/eslint-plugin.js +2 -2
  22. package/dist/eslint-plugin.js.map +1 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +6 -10
  25. package/dist/index.js.map +1 -1
  26. package/dist/localization.d.ts.map +1 -1
  27. package/dist/localization.js +19 -5
  28. package/dist/localization.js.map +1 -1
  29. package/dist/overrides/Head.astro +3 -0
  30. package/dist/overrides/Header.astro +8 -0
  31. package/dist/overrides/LanguageSelect.astro +29 -35
  32. package/dist/overrides/MobileMenuFooter.astro +1 -1
  33. package/dist/overrides/Search.astro +25 -1
  34. package/dist/overrides/ThemeSelect.astro +2 -0
  35. package/dist/routes/Page.astro +1 -0
  36. package/dist/styling.d.ts.map +1 -1
  37. package/dist/styling.js +1 -1
  38. package/dist/{tasty-states-BDKIbfw2.js → tasty-states-rTLFy26t.js} +5 -13
  39. package/dist/tasty-states-rTLFy26t.js.map +1 -0
  40. package/dist/ui.d.ts.map +1 -1
  41. package/dist/ui.js +2 -0
  42. package/dist/ui.js.map +1 -1
  43. package/package.json +2 -2
  44. package/dist/tasty-states-BDKIbfw2.js.map +0 -1
@@ -1,5 +1,6 @@
1
1
  import { tasty } from "@tenphi/tasty";
2
2
  import { customizeComponent } from "./customize-component.js";
3
+ import { selectPopoverStyles } from "./select-popover-styles.js";
3
4
  import { configureCookbookStates } from "./tasty-states.js";
4
5
 
5
6
  configureCookbookStates();
@@ -117,56 +118,37 @@ export const PackageVersionRoot = customizeComponent(
117
118
  }),
118
119
  );
119
120
 
121
+ const versionSelectStyles = selectPopoverStyles({
122
+ option: "Link",
123
+ hoverOption: "HoverLink",
124
+ currentOption: "CurrentLink",
125
+ });
126
+
120
127
  export const VersionSwitcherRoot = customizeComponent(
121
128
  "VersionSwitcher",
122
129
  tasty({
123
- as: "details",
130
+ as: "div",
124
131
  styles: {
132
+ ...versionSelectStyles,
125
133
  display: "inline-flex",
126
- position: "relative",
127
134
  flexShrink: "0",
128
- color: "#text-soft",
129
135
  Trigger: {
130
- $: "> summary",
131
- display: "flex",
132
- alignItems: "center",
136
+ ...versionSelectStyles.Trigger,
133
137
  blockSize: "min $control-height",
134
138
  inlinePadding: "$gap",
135
139
  fill: "#surface-2",
136
140
  border: true,
137
- radius: "$header-control-radius",
138
141
  preset: "small / strong",
139
- cursor: "pointer",
140
- whiteSpace: "nowrap",
142
+ anchorName: "--version-trigger",
141
143
  },
142
144
  Panel: {
143
- $: "> nav",
144
- position: "absolute",
145
- inset: { "": "100% auto auto 0", "@mobile": "100% 0 auto auto" },
146
- zIndex: "10",
147
- inlineSize: "min 8rem",
148
- padding: "($gap * 0.5)",
149
- fill: "#surface",
150
- border: true,
151
- radius: "$radius",
152
- shadow: "0 0.75rem 2rem #shadow",
153
- },
154
- OpenPanel: {
155
- $: "&[open] > nav",
156
- display: "grid",
157
- },
158
- Link: {
159
- $: "> nav > a",
160
- display: "block",
161
- padding: "($gap * 0.5) $gap",
162
- color: "#text-soft",
163
- preset: "small",
164
- textDecoration: "none",
165
- },
166
- CurrentLink: {
167
- $: '> nav > a[aria-current="page"]',
168
- color: "#accent-text",
169
- preset: "small / strong",
145
+ ...versionSelectStyles.Panel,
146
+ positionAnchor: "--version-trigger",
147
+ blockInset: "(anchor(bottom) + $gap) start, auto end",
148
+ inlineInset: {
149
+ "": "anchor(left) start, auto end",
150
+ "@mobile": "auto start, anchor(right) end",
151
+ },
170
152
  },
171
153
  },
172
154
  }),
@@ -320,6 +302,15 @@ export const HeaderRoot = customizeComponent(
320
302
  inlineSize: "$docs-menu-button-size",
321
303
  blockSize: "$docs-menu-button-size",
322
304
  },
305
+ MobileLanguage: {
306
+ $: ".td-header__mobile-language",
307
+ display: "grid",
308
+ hide: { "": true, "@mobile": false },
309
+ flexShrink: "0",
310
+ order: "1",
311
+ inlineSize: "$docs-menu-button-size",
312
+ blockSize: "$docs-menu-button-size",
313
+ },
323
314
  },
324
315
  }),
325
316
  );
@@ -394,9 +385,9 @@ export const ThemeSelectRoot = customizeComponent(
394
385
  },
395
386
  },
396
387
  OpenPanel: {
397
- $: "[popover]:popover-open",
398
- opacity: { "": "1", "@starting": "0" },
399
- scale: { "": "1", "@starting": "1 0.96" },
388
+ $: "[popover]:popover-open[data-open]",
389
+ opacity: "1",
390
+ scale: "1",
400
391
  },
401
392
  Section: {
402
393
  $: "fieldset",
@@ -745,7 +736,7 @@ export const HeaderLinksRoot = customizeComponent(
745
736
  shadow: "0 0.75rem 2rem #shadow",
746
737
  opacity: "0",
747
738
  scale: "1 0.96",
748
- transformOrigin: "top right",
739
+ transformOrigin: "top",
749
740
  transition: {
750
741
  "": "none",
751
742
  "!@reduced-motion":
@@ -14,7 +14,7 @@ const ui = messages(
14
14
  ---
15
15
 
16
16
  <PreviewRoot
17
- className="td-preview"
17
+ className="td-preview not-content"
18
18
  aria-label={title}
19
19
  data-tasty-anatomy="Preview"
20
20
  >
@@ -0,0 +1,64 @@
1
+ ---
2
+ import Icon from "./Icon.astro";
3
+
4
+ interface Option {
5
+ href: string;
6
+ label: string;
7
+ lang?: string;
8
+ hint?: string;
9
+ current?: boolean;
10
+ }
11
+
12
+ interface Props {
13
+ triggerLabel: string;
14
+ selectedLabel: string;
15
+ title: string;
16
+ options: Option[];
17
+ icon?: string;
18
+ }
19
+
20
+ const { triggerLabel, selectedLabel, title, options, icon } = Astro.props;
21
+ const id = `select-${crypto.randomUUID()}`;
22
+ ---
23
+
24
+ <button
25
+ type="button"
26
+ popovertarget={id}
27
+ aria-label={triggerLabel}
28
+ title={title}
29
+ >
30
+ {icon && <Icon name={icon} class="label-icon" />}
31
+ <span class="trigger-label">{selectedLabel}</span>
32
+ <Icon name="down-caret" class="caret" />
33
+ </button>
34
+ <div
35
+ id={id}
36
+ popover="auto"
37
+ role="group"
38
+ aria-label={title}
39
+ data-select-popover-panel
40
+ >
41
+ <div class="panel-title">{title}</div>
42
+ <nav aria-label={title}>
43
+ {
44
+ options.map((option) => (
45
+ <a
46
+ href={option.href}
47
+ aria-current={option.current ? "page" : undefined}
48
+ >
49
+ <span lang={option.lang}>{option.label}</span>
50
+ {option.hint && <span class="fallback-label">({option.hint})</span>}
51
+ <Icon name="approve-check" class="checkmark" />
52
+ </a>
53
+ ))
54
+ }
55
+ </nav>
56
+ </div>
57
+
58
+ <script>
59
+ import { initializePopoverMotion } from "../client/popover-motion.js";
60
+
61
+ document
62
+ .querySelectorAll<HTMLElement>("[data-select-popover-panel]")
63
+ .forEach((panel) => initializePopoverMotion(panel));
64
+ </script>
@@ -84,13 +84,13 @@ export const PreviewRoot = customizeComponent(
84
84
  fill: "#surface-2",
85
85
  },
86
86
  Stage: {
87
- padding: "3x",
87
+ padding: "2x",
88
88
  fill: "#surface",
89
89
  },
90
90
  Frame: {
91
91
  display: "block",
92
92
  width: "100%",
93
- height: "min 18rem",
93
+ height: "min 10rem",
94
94
  border: "0",
95
95
  fill: "#surface",
96
96
  },
@@ -102,9 +102,23 @@ export const PreviewRoot = customizeComponent(
102
102
  preset: "small",
103
103
  fill: "#surface-2",
104
104
  cursor: "pointer",
105
+ transition: "fill $transition",
106
+ },
107
+ HoverSummary: {
108
+ $: "> details > summary:hover",
109
+ fill: "#surface-2-hover",
110
+ },
111
+ ActiveSummary: {
112
+ $: "> details > summary:active",
113
+ fill: "#surface-2-pressed",
105
114
  },
106
115
  Pre: {
107
116
  margin: "0",
117
+ padding: "2x",
118
+ overflowX: "auto",
119
+ color: "#syntax-text",
120
+ fill: "#syntax-bg",
121
+ preset: "code",
108
122
  radius: "0",
109
123
  },
110
124
  },
@@ -4,6 +4,7 @@ import { content } from "virtual:cookbook/config";
4
4
  import type { DocsRoute, SiteVersion } from "@tenphi/docs";
5
5
  import { versionLinks } from "../versioning.js";
6
6
  import { VersionSwitcherRoot } from "./LayoutComponents.js";
7
+ import SelectPopover from "./SelectPopover.astro";
7
8
 
8
9
  interface Props {
9
10
  versions: SiteVersion[];
@@ -23,22 +24,14 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
23
24
  ---
24
25
 
25
26
  <VersionSwitcherRoot data-tasty-anatomy="VersionSwitcher">
26
- <summary
27
- aria-label={`${ui.documentationVersion}: ${current?.label ?? ui.versions}`}
28
- >{current?.label ?? ui.versions}</summary
29
- >
30
- <nav aria-label={ui.documentationVersions}>
31
- {
32
- links.map((version) => (
33
- <a
34
- href={version.href}
35
- aria-current={
36
- version.routeBase === current?.routeBase ? "page" : undefined
37
- }
38
- >
39
- {version.label}
40
- </a>
41
- ))
42
- }
43
- </nav>
27
+ <SelectPopover
28
+ triggerLabel={`${ui.documentationVersion}: ${current?.label ?? ui.versions}`}
29
+ selectedLabel={current?.label ?? ui.versions}
30
+ title={ui.documentationVersions}
31
+ options={links.map((version) => ({
32
+ href: version.href,
33
+ label: version.label,
34
+ current: version.routeBase === current?.routeBase,
35
+ }))}
36
+ />
44
37
  </VersionSwitcherRoot>
@@ -1,7 +1,6 @@
1
1
  import { afterEach, describe, expect, it } from "vitest";
2
2
  import {
3
3
  configureComponentStyles,
4
- resolveLegacyAnatomyStyles,
5
4
  resolveComponentStyleOverride,
6
5
  resolveComponentStyles,
7
6
  unusedCustomStyleNames,
@@ -97,19 +96,7 @@ describe("component style configuration", () => {
97
96
  });
98
97
  });
99
98
 
100
- it("keeps custom anatomy styles on the compatibility bridge", () => {
101
- expect(
102
- resolveLegacyAnatomyStyles({
103
- Footer: { color: "#text-muted" },
104
- ThemeSelect: { padding: "1x" },
105
- ProductBadge: { color: "#accent-text" },
106
- }),
107
- ).toEqual({
108
- '[data-tasty-anatomy="ProductBadge"]': { color: "#accent-text" },
109
- });
110
- });
111
-
112
- it("reports only custom style names without a component or anatomy match", () => {
99
+ it("reports only custom style names without a component style resolver", () => {
113
100
  const styles = {
114
101
  ProjectBadge: { color: "#accent-text" },
115
102
  ProjectNote: { color: "#text" },
@@ -117,13 +104,10 @@ describe("component style configuration", () => {
117
104
  };
118
105
  configureComponentStyles(styles);
119
106
  resolveComponentStyles("ProjectBadge", { color: "#text" });
107
+ resolveComponentStyles("ProjectNote", { color: "#text" });
120
108
 
121
- expect(unusedCustomStyleNames(styles, new Set(["ProjectNote"]))).toEqual([
122
- "ProjectBadg",
123
- ]);
109
+ expect(unusedCustomStyleNames(styles)).toEqual(["ProjectBadg"]);
124
110
  configureComponentStyles(styles);
125
- expect(unusedCustomStyleNames(styles, new Set())).toEqual(
126
- Object.keys(styles),
127
- );
111
+ expect(unusedCustomStyleNames(styles)).toEqual(Object.keys(styles));
128
112
  });
129
113
  });
@@ -1,5 +1,4 @@
1
1
  import { mergeStyles, type Styles } from "@tenphi/tasty/core";
2
- import { COOKBOOK_COMPONENT_NAMES } from "@tenphi/docs";
3
2
 
4
3
  // Astro can load the integration and renderer through separate module graphs.
5
4
  // Keep their component configuration on the shared process global.
@@ -7,7 +6,6 @@ const sharedConfiguration = globalThis as typeof globalThis & {
7
6
  __tenphiCookbookComponentStyles?: Record<string, Styles | undefined>;
8
7
  __tenphiCookbookUsedComponentStyles?: Set<string>;
9
8
  };
10
- const cookbookComponentNames = new Set<string>(COOKBOOK_COMPONENT_NAMES);
11
9
 
12
10
  export function configureComponentStyles(
13
11
  styles: Record<string, Styles | undefined> | undefined,
@@ -29,15 +27,13 @@ export function resolveComponentStyles(
29
27
  : baseStyles;
30
28
  }
31
29
 
32
- /** Find custom names without a component style resolver or rendered anatomy. */
30
+ /** Find custom names without a component style resolver match. */
33
31
  export function unusedCustomStyleNames(
34
32
  styles: Record<string, Styles> | undefined,
35
- anatomyNames: ReadonlySet<string>,
36
33
  ): string[] {
37
34
  return Object.keys(styles ?? {}).filter(
38
35
  (name) =>
39
- !sharedConfiguration.__tenphiCookbookUsedComponentStyles?.has(name) &&
40
- !anatomyNames.has(name),
36
+ !sharedConfiguration.__tenphiCookbookUsedComponentStyles?.has(name),
41
37
  );
42
38
  }
43
39
 
@@ -47,19 +43,3 @@ export function resolveComponentStyleOverride(
47
43
  return sharedConfiguration.__tenphiCookbookComponentStyles?.[name] as
48
44
  Styles | undefined;
49
45
  }
50
-
51
- /** Preserve custom anatomy names from the pre-component style API. */
52
- export function resolveLegacyAnatomyStyles(
53
- styles: Record<string, Styles | undefined> | undefined,
54
- ): Record<string, Styles> | undefined {
55
- if (!styles) return undefined;
56
- const entries = Object.entries(styles)
57
- .filter(
58
- (entry): entry is [string, Styles] =>
59
- !cookbookComponentNames.has(entry[0]) && entry[1] !== undefined,
60
- )
61
- .map(([name, value]) => [`[data-tasty-anatomy="${name}"]`, value]);
62
- return entries.length
63
- ? (Object.fromEntries(entries) as Record<string, Styles>)
64
- : undefined;
65
- }
@@ -0,0 +1,107 @@
1
+ /** Shared server-side styles for the language and version selectors. */
2
+ export function selectPopoverStyles({
3
+ option = "Option",
4
+ hoverOption = "HoverOption",
5
+ currentOption = "CurrentOption",
6
+ } = {}) {
7
+ return {
8
+ "$popover-transition": "120ms",
9
+ Trigger: {
10
+ $: "> button",
11
+ display: "flex",
12
+ alignItems: "center",
13
+ justifyContent: "center",
14
+ gap: "($gap * 0.5)",
15
+ color: "#text-soft",
16
+ radius: "$header-control-radius",
17
+ preset: "small",
18
+ cursor: "pointer",
19
+ },
20
+ HoverTrigger: {
21
+ $: "> button:hover, &:has([popover]:popover-open) > button",
22
+ color: "#text",
23
+ fill: "#surface-2-hover",
24
+ },
25
+ TriggerLabel: {
26
+ $: ".trigger-label",
27
+ overflow: "hidden",
28
+ textOverflow: "ellipsis",
29
+ whiteSpace: "nowrap",
30
+ },
31
+ Caret: {
32
+ $: "> button > .caret",
33
+ flexShrink: "0",
34
+ inlineSize: "0.875rem",
35
+ blockSize: "0.875rem",
36
+ },
37
+ Panel: {
38
+ $: "> [popover]",
39
+ position: "fixed",
40
+ inset: "auto",
41
+ inlineSize: "min(15rem, calc(100vw - 2 * $docs-nav-pad-x))",
42
+ blockSize: "max (100dvh - $docs-nav-height - $gap)",
43
+ overflowY: "auto",
44
+ margin: "0",
45
+ padding: "$gap",
46
+ color: "#text",
47
+ fill: "#surface-2",
48
+ border: true,
49
+ radius: "$card-radius",
50
+ shadow: "0 0.75rem 2rem #shadow",
51
+ opacity: "0",
52
+ scale: "1 0.96",
53
+ transformOrigin: "top",
54
+ transition: {
55
+ "": "none",
56
+ "!@reduced-motion":
57
+ "opacity $popover-transition ease-out, scale $popover-transition ease-out, display $popover-transition allow-discrete, overlay $popover-transition allow-discrete",
58
+ },
59
+ },
60
+ OpenPanel: {
61
+ $: "> [popover]:popover-open[data-open]",
62
+ opacity: "1",
63
+ scale: "1",
64
+ },
65
+ PanelTitle: {
66
+ $: ".panel-title",
67
+ padding: "($gap * 0.75) $gap",
68
+ color: "#text-muted",
69
+ preset: "small / strong",
70
+ },
71
+ Options: { $: "nav", display: "grid", gap: "($gap * 0.25)" },
72
+ [option]: {
73
+ $: "nav a",
74
+ display: "flex",
75
+ alignItems: "center",
76
+ gap: "$gap",
77
+ minBlockSize: "2.25rem",
78
+ padding: "($gap * 0.75) $gap",
79
+ color: "#text-soft",
80
+ preset: "small",
81
+ textDecoration: "none",
82
+ radius: "$radius",
83
+ },
84
+ [hoverOption]: {
85
+ $: "nav a:hover",
86
+ color: "#text",
87
+ fill: "#surface-2-hover",
88
+ },
89
+ [currentOption]: {
90
+ $: 'nav a[aria-current="page"]',
91
+ color: "#accent-text",
92
+ fill: "#accent-surface-2-subtle",
93
+ },
94
+ Checkmark: {
95
+ $: "nav a > .checkmark",
96
+ flexShrink: "0",
97
+ inlineMargin: "auto start",
98
+ inlineSize: "1rem",
99
+ blockSize: "1rem",
100
+ visibility: "hidden",
101
+ },
102
+ SelectedCheckmark: {
103
+ $: 'nav a[aria-current="page"] > .checkmark',
104
+ visibility: "visible",
105
+ },
106
+ };
107
+ }
@@ -140,8 +140,8 @@ function createValidationConfig(theme = {}) {
140
140
  ...tasty_config_default,
141
141
  tokens: [
142
142
  ...tasty_config_default.tokens,
143
- ...Object.keys(theme.tokens ?? {}).map((name) => name.startsWith("--") ? `$${name.slice(2)}` : name),
144
- ...Object.keys(theme.palette ?? {}).map((name) => `#${name === "textSoft" ? "text-soft" : name}`)
143
+ ...Object.keys(theme.tokens ?? {}),
144
+ ...Object.keys(theme.palette ?? {}).map((name) => `#${name}`)
145
145
  ],
146
146
  units: [...tasty_config_default.units, ...Object.keys(theme.units ?? {})],
147
147
  states: [...tasty_config_default.states, ...Object.keys(theme.states ?? {})],
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-plugin.js","names":["validationConfig"],"sources":["../src/tasty.config.ts","../src/eslint-plugin.ts"],"sourcesContent":["import type { TastyValidationConfig } from \"@tenphi/eslint-plugin-tasty\";\n\nexport default {\n importSources: [\"@tenphi/cookbook/styling\", \"@tenphi/renderer/styling\"],\n styleFunctions: {\n defineComponent: { argument: 1, kind: \"options\" },\n resolveComponentStyles: { argument: 1, kind: \"styles\" },\n mergeStyles: { argument: \"all\", kind: \"styles\", partial: true },\n },\n tokens: [\n \"$gap\",\n \"$radius\",\n \"$header-control-radius\",\n \"$card-radius\",\n \"$border-width\",\n \"$outline-width\",\n \"$outline-offset\",\n \"$layout-width\",\n \"$content-width\",\n \"$sidebar-width\",\n \"$control-height\",\n \"$transition\",\n \"$sharp-radius\",\n \"$bold-font-weight\",\n \"#white\",\n \"#black\",\n \"#clear\",\n \"#current\",\n \"#surface\",\n \"#header\",\n \"#heading\",\n \"#surface-2\",\n \"#surface-3\",\n \"#surface-2-hover\",\n \"#surface-2-pressed\",\n \"#surface-3-hover\",\n \"#surface-3-pressed\",\n \"#text\",\n \"#text-soft\",\n \"#text-muted\",\n \"#sidebar-text\",\n \"#border\",\n \"#border-strong\",\n \"#accent-text\",\n \"#accent-surface\",\n \"#accent-surface-text\",\n \"#logo-surface\",\n \"#logo-mark\",\n \"#accent-surface-subtle\",\n \"#accent-surface-2-subtle\",\n \"#focus\",\n \"#shadow\",\n \"#overlay\",\n \"#syntax-bg\",\n \"#syntax-text\",\n \"#syntax-comment\",\n \"#syntax-punctuation\",\n \"#syntax-keyword\",\n \"#syntax-string\",\n \"#syntax-token\",\n \"#syntax-property\",\n \"#syntax-number\",\n \"#syntax-function\",\n \"#syntax-value\",\n \"#syntax-operator\",\n \"#info\",\n \"#info-surface\",\n \"#info-text\",\n \"#success\",\n \"#success-surface\",\n \"#success-text\",\n \"#warning\",\n \"#warning-surface\",\n \"#warning-text\",\n \"#danger\",\n \"#danger-surface\",\n \"#danger-text\",\n \"#orange-surface\",\n \"#orange\",\n \"#orange-text\",\n \"#green-surface\",\n \"#green\",\n \"#green-text\",\n \"#blue-surface\",\n \"#blue\",\n \"#blue-text\",\n \"#purple-surface\",\n \"#purple\",\n \"#purple-text\",\n \"#red-surface\",\n \"#red\",\n \"#red-text\",\n ],\n units: [\"x\", \"r\", \"cr\", \"bw\"],\n states: [\n \"@mobile\",\n \"@desktop\",\n \"@small\",\n \"@compact\",\n \"@shell-mobile\",\n \"@shell-desktop\",\n \"@narrow-layout\",\n \"@medium-layout\",\n \"@reduced-motion\",\n ],\n presets: [\n \"body\",\n \"heading\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"navigation\",\n \"small\",\n \"code\",\n ],\n} satisfies TastyValidationConfig;\n","export { default, recommended, strict } from \"@tenphi/eslint-plugin-tasty\";\nexport type {\n ResolvedConfig,\n StyleFunctionConfig,\n TastyValidationConfig,\n} from \"@tenphi/eslint-plugin-tasty\";\nexport { default as validationConfig } from \"./tasty.config.js\";\n\nimport type { ThemeConfig } from \"@tenphi/docs\";\nimport type { TastyValidationConfig } from \"@tenphi/eslint-plugin-tasty\";\nimport validationConfig from \"./tasty.config.js\";\n\n/** Keep editor/linter names aligned with a Cookbook theme. */\nexport function createValidationConfig(\n theme: ThemeConfig = {},\n): TastyValidationConfig {\n return {\n ...validationConfig,\n tokens: [\n ...validationConfig.tokens,\n ...Object.keys(theme.tokens ?? {}).map((name) =>\n name.startsWith(\"--\") ? `$${name.slice(2)}` : name,\n ),\n ...Object.keys(theme.palette ?? {}).map(\n (name) => `#${name === \"textSoft\" ? \"text-soft\" : name}`,\n ),\n ],\n units: [...validationConfig.units, ...Object.keys(theme.units ?? {})],\n states: [...validationConfig.states, ...Object.keys(theme.states ?? {})],\n presets: [...validationConfig.presets, ...Object.keys(theme.presets ?? {})],\n recipes: Object.keys(theme.recipes ?? {}),\n };\n}\n"],"mappings":";;AAEA,IAAA,uBAAe;CACb,eAAe,CAAC,4BAA4B,0BAA0B;CACtE,gBAAgB;EACd,iBAAiB;GAAE,UAAU;GAAG,MAAM;EAAU;EAChD,wBAAwB;GAAE,UAAU;GAAG,MAAM;EAAS;EACtD,aAAa;GAAE,UAAU;GAAO,MAAM;GAAU,SAAS;EAAK;CAChE;CACA,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,OAAO;EAAC;EAAK;EAAK;EAAM;CAAI;CAC5B,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;ACzGA,SAAgB,uBACd,QAAqB,CAAC,GACC;CACvB,OAAO;EACL,GAAGA;EACH,QAAQ;GACN,GAAGA,qBAAiB;GACpB,GAAG,OAAO,KAAK,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,SACtC,KAAK,WAAW,IAAI,IAAI,IAAI,KAAK,MAAM,CAAC,MAAM,IAChD;GACA,GAAG,OAAO,KAAK,MAAM,WAAW,CAAC,CAAC,CAAC,CAAC,KACjC,SAAS,IAAI,SAAS,aAAa,cAAc,MACpD;EACF;EACA,OAAO,CAAC,GAAGA,qBAAiB,OAAO,GAAG,OAAO,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC;EACpE,QAAQ,CAAC,GAAGA,qBAAiB,QAAQ,GAAG,OAAO,KAAK,MAAM,UAAU,CAAC,CAAC,CAAC;EACvE,SAAS,CAAC,GAAGA,qBAAiB,SAAS,GAAG,OAAO,KAAK,MAAM,WAAW,CAAC,CAAC,CAAC;EAC1E,SAAS,OAAO,KAAK,MAAM,WAAW,CAAC,CAAC;CAC1C;AACF"}
1
+ {"version":3,"file":"eslint-plugin.js","names":["validationConfig"],"sources":["../src/tasty.config.ts","../src/eslint-plugin.ts"],"sourcesContent":["import type { TastyValidationConfig } from \"@tenphi/eslint-plugin-tasty\";\n\nexport default {\n importSources: [\"@tenphi/cookbook/styling\", \"@tenphi/renderer/styling\"],\n styleFunctions: {\n defineComponent: { argument: 1, kind: \"options\" },\n resolveComponentStyles: { argument: 1, kind: \"styles\" },\n mergeStyles: { argument: \"all\", kind: \"styles\", partial: true },\n },\n tokens: [\n \"$gap\",\n \"$radius\",\n \"$header-control-radius\",\n \"$card-radius\",\n \"$border-width\",\n \"$outline-width\",\n \"$outline-offset\",\n \"$layout-width\",\n \"$content-width\",\n \"$sidebar-width\",\n \"$control-height\",\n \"$transition\",\n \"$sharp-radius\",\n \"$bold-font-weight\",\n \"#white\",\n \"#black\",\n \"#clear\",\n \"#current\",\n \"#surface\",\n \"#header\",\n \"#heading\",\n \"#surface-2\",\n \"#surface-3\",\n \"#surface-2-hover\",\n \"#surface-2-pressed\",\n \"#surface-3-hover\",\n \"#surface-3-pressed\",\n \"#text\",\n \"#text-soft\",\n \"#text-muted\",\n \"#sidebar-text\",\n \"#border\",\n \"#border-strong\",\n \"#accent-text\",\n \"#accent-surface\",\n \"#accent-surface-text\",\n \"#logo-surface\",\n \"#logo-mark\",\n \"#accent-surface-subtle\",\n \"#accent-surface-2-subtle\",\n \"#focus\",\n \"#shadow\",\n \"#overlay\",\n \"#syntax-bg\",\n \"#syntax-text\",\n \"#syntax-comment\",\n \"#syntax-punctuation\",\n \"#syntax-keyword\",\n \"#syntax-string\",\n \"#syntax-token\",\n \"#syntax-property\",\n \"#syntax-number\",\n \"#syntax-function\",\n \"#syntax-value\",\n \"#syntax-operator\",\n \"#info\",\n \"#info-surface\",\n \"#info-text\",\n \"#success\",\n \"#success-surface\",\n \"#success-text\",\n \"#warning\",\n \"#warning-surface\",\n \"#warning-text\",\n \"#danger\",\n \"#danger-surface\",\n \"#danger-text\",\n \"#orange-surface\",\n \"#orange\",\n \"#orange-text\",\n \"#green-surface\",\n \"#green\",\n \"#green-text\",\n \"#blue-surface\",\n \"#blue\",\n \"#blue-text\",\n \"#purple-surface\",\n \"#purple\",\n \"#purple-text\",\n \"#red-surface\",\n \"#red\",\n \"#red-text\",\n ],\n units: [\"x\", \"r\", \"cr\", \"bw\"],\n states: [\n \"@mobile\",\n \"@desktop\",\n \"@small\",\n \"@compact\",\n \"@shell-mobile\",\n \"@shell-desktop\",\n \"@narrow-layout\",\n \"@medium-layout\",\n \"@reduced-motion\",\n ],\n presets: [\n \"body\",\n \"heading\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"navigation\",\n \"small\",\n \"code\",\n ],\n} satisfies TastyValidationConfig;\n","export { default, recommended, strict } from \"@tenphi/eslint-plugin-tasty\";\nexport type {\n ResolvedConfig,\n StyleFunctionConfig,\n TastyValidationConfig,\n} from \"@tenphi/eslint-plugin-tasty\";\nexport { default as validationConfig } from \"./tasty.config.js\";\n\nimport type { ThemeConfig } from \"@tenphi/docs\";\nimport type { TastyValidationConfig } from \"@tenphi/eslint-plugin-tasty\";\nimport validationConfig from \"./tasty.config.js\";\n\n/** Keep editor/linter names aligned with a Cookbook theme. */\nexport function createValidationConfig(\n theme: ThemeConfig = {},\n): TastyValidationConfig {\n return {\n ...validationConfig,\n tokens: [\n ...validationConfig.tokens,\n ...Object.keys(theme.tokens ?? {}),\n ...Object.keys(theme.palette ?? {}).map((name) => `#${name}`),\n ],\n units: [...validationConfig.units, ...Object.keys(theme.units ?? {})],\n states: [...validationConfig.states, ...Object.keys(theme.states ?? {})],\n presets: [...validationConfig.presets, ...Object.keys(theme.presets ?? {})],\n recipes: Object.keys(theme.recipes ?? {}),\n };\n}\n"],"mappings":";;AAEA,IAAA,uBAAe;CACb,eAAe,CAAC,4BAA4B,0BAA0B;CACtE,gBAAgB;EACd,iBAAiB;GAAE,UAAU;GAAG,MAAM;EAAU;EAChD,wBAAwB;GAAE,UAAU;GAAG,MAAM;EAAS;EACtD,aAAa;GAAE,UAAU;GAAO,MAAM;GAAU,SAAS;EAAK;CAChE;CACA,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,OAAO;EAAC;EAAK;EAAK;EAAM;CAAI;CAC5B,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;ACzGA,SAAgB,uBACd,QAAqB,CAAC,GACC;CACvB,OAAO;EACL,GAAGA;EACH,QAAQ;GACN,GAAGA,qBAAiB;GACpB,GAAG,OAAO,KAAK,MAAM,UAAU,CAAC,CAAC;GACjC,GAAG,OAAO,KAAK,MAAM,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,MAAM;EAC9D;EACA,OAAO,CAAC,GAAGA,qBAAiB,OAAO,GAAG,OAAO,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC;EACpE,QAAQ,CAAC,GAAGA,qBAAiB,QAAQ,GAAG,OAAO,KAAK,MAAM,UAAU,CAAC,CAAC,CAAC;EACvE,SAAS,CAAC,GAAGA,qBAAiB,SAAS,GAAG,OAAO,KAAK,MAAM,WAAW,CAAC,CAAC,CAAC;EAC1E,SAAS,OAAO,KAAK,MAAM,WAAW,CAAC,CAAC;CAC1C;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/plugin-contract.ts","../src/integration.ts"],"mappings":";;;;;KAEY;EAEN,WAAW,iBAAiB,QAAQ;;EAGpC,MAAM,iBAAiB;;;;UCiGZ;EACf,SAAS;EACT;EACA;;EAEA,oBAAoB;;iBAGE,SACtB,UAAS,kBACR"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/plugin-contract.ts","../src/integration.ts"],"mappings":";;;;;KAEY;EAEN,WAAW,iBAAiB,QAAQ;;EAGpC,MAAM,iBAAiB;;;;UC+FZ;EACf,SAAS;EACT;EACA;;EAEA,oBAAoB;;iBAGE,SACtB,UAAS,kBACR"}
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { localeAlternates } from "./localization.js";
3
3
  import { DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS, resolveThemeTokens, resolveTypographyPresets } from "./theme/defaults.js";
4
4
  import { configureCodeHighlighting, cookbookShikiConfig } from "./theme/shiki-theme.js";
5
5
  import { TASTY_UNITS, tastyTokens } from "./theme/tasty-config.js";
6
- import { a as resolveLegacyAnatomyStyles, n as cookbookStates, o as unusedCustomStyleNames, r as configureComponentStyles } from "./tasty-states-BDKIbfw2.js";
6
+ import { a as unusedCustomStyleNames, n as cookbookStates, r as configureComponentStyles } from "./tasty-states-rTLFy26t.js";
7
7
  import { agentPagePath } from "./page-metadata.js";
8
8
  import { createRequire } from "node:module";
9
9
  import { cp, mkdir, readFile, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
@@ -904,9 +904,9 @@ async function createDefaultSocialImage(site, base, colors) {
904
904
  const origin = site.url ? new URL(site.url).host : "";
905
905
  const surface = toHex(colors.surface.light);
906
906
  const heading = toHex(colors.heading.light);
907
- const soft = toHex(colors.textSoft.light);
908
- const accent = toHex(colors.accentText.light);
909
- const accentSurface = toHex(colors.accentSurface.light);
907
+ const soft = toHex(colors["text-soft"].light);
908
+ const accent = toHex(colors["accent-text"].light);
909
+ const accentSurface = toHex(colors["accent-surface"].light);
910
910
  const artwork = Buffer.from(`<svg xmlns="http://www.w3.org/2000/svg" width="${WIDTH}" height="${HEIGHT}" viewBox="0 0 ${WIDTH} ${HEIGHT}">
911
911
  <rect width="${WIDTH}" height="${HEIGHT}" fill="${surface}"/>
912
912
  <rect width="14" height="${HEIGHT}" fill="${accent}"/>
@@ -1530,17 +1530,15 @@ function configuredCookbook(options) {
1530
1530
  "astro:build:done": async (context) => {
1531
1531
  await callInner(inner, "astro:build:done", context);
1532
1532
  const output = fileURLToPath(context.dir);
1533
- const anatomyNames = /* @__PURE__ */ new Set();
1534
1533
  for (const relativePath of await readdir(output, { recursive: true })) {
1535
1534
  if (extname(relativePath) !== ".html") continue;
1536
1535
  const path = join(output, relativePath);
1537
1536
  const html = await readFile(path, "utf8");
1538
- for (const match of html.matchAll(/\bdata-tasty-anatomy="([^"]+)"/g)) anatomyNames.add(match[1]);
1539
1537
  const sanitized = html.replace(/\s*<link\b(?=[^>]*rel="stylesheet")(?=[^>]*href="data:text\/css,")[^>]*>/g, "").replace(/\s*<style>\s*<\/style>/g, "").replace(/<style>astro-island,astro-slot,astro-static-slot\{display:contents\}<\/style>/g, "");
1540
1538
  assertTastyOutput(sanitized, relativePath);
1541
1539
  if (sanitized !== html) await writeFile(path, sanitized);
1542
1540
  }
1543
- for (const name of unusedCustomStyleNames(options.config?.theme?.customStyles, anatomyNames)) context.logger.warn(`theme.customStyles.${name} did not match a component style resolver or rendered data-tasty-anatomy attribute. Check that its name matches defineComponent() or resolveComponentStyles().`);
1541
+ for (const name of unusedCustomStyleNames(options.config?.theme?.customStyles)) context.logger.warn(`theme.customStyles.${name} did not match a component style resolver. Check that its name matches defineComponent() or resolveComponentStyles().`);
1544
1542
  if (graph?.config.search.enabled !== false) try {
1545
1543
  const { index, errors } = await pagefind.createIndex();
1546
1544
  if (errors.length || !index) throw new Error(errors.join("\n") || "Pagefind did not create an index.");
@@ -1667,7 +1665,6 @@ function errorMessage(error) {
1667
1665
  }
1668
1666
  function configureTastyTheme(theme, resolved) {
1669
1667
  const tokens = tastyTokens(resolved);
1670
- const globalStyles = resolveLegacyAnatomyStyles(theme?.customStyles);
1671
1668
  globalThis.__tenphiCookbookTastyRuntime = {
1672
1669
  units: {
1673
1670
  ...TASTY_UNITS,
@@ -1689,8 +1686,7 @@ function configureTastyTheme(theme, resolved) {
1689
1686
  },
1690
1687
  recipes: theme?.recipes ?? {},
1691
1688
  tokens,
1692
- presets: resolved.presets,
1693
- ...globalStyles ? { globalStyles } : {}
1689
+ presets: resolved.presets
1694
1690
  });
1695
1691
  }
1696
1692
  async function callInner(integrations, hook, context) {