@magentofullstackdev/hyperion-shared 0.0.0-stage → 0.9.0-beta.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sergiu Ro -- magentofullstackdev
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 CHANGED
@@ -1,3 +1,79 @@
1
- # Temporary Holding Version
1
+ # @magentofullstackdev/hyperion-shared
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Shared design tokens, Tailwind preset, and base Lit element / mixins for the
4
+ [Hyperion](https://github.com/magentofullstackdev/hyperion) Magento 2 theme
5
+ suite.
6
+
7
+ This package is published as TypeScript / CSS source (a beta, `0.9.0-beta.x`,
8
+ versioned with the suite). It has no build step: sibling packages
9
+ (`@magentofullstackdev/hyperion-theme`, `@magentofullstackdev/hyperion-checkout`)
10
+ consume it directly through their own bundler (Vite). Installing it does not
11
+ install or activate anything in Magento; the storefront comes from the
12
+ Composer packages, see
13
+ [`docs/install.md`](https://github.com/magentofullstackdev/hyperion/blob/main/docs/install.md).
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install @magentofullstackdev/hyperion-shared
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ Tailwind preset:
24
+
25
+ ```ts
26
+ // tailwind.config.ts
27
+ import hyperionPreset from '@magentofullstackdev/hyperion-shared/tailwind/preset';
28
+
29
+ export default {
30
+ presets: [hyperionPreset],
31
+ content: ['./src/**/*.{ts,tsx,js,html}'],
32
+ };
33
+ ```
34
+
35
+ Design tokens (CSS):
36
+
37
+ ```css
38
+ /* your-theme.css */
39
+ @import "@magentofullstackdev/hyperion-shared/tokens/index.css";
40
+ ```
41
+
42
+ Base Lit element:
43
+
44
+ ```ts
45
+ import { HyperionLightElement } from '@magentofullstackdev/hyperion-shared/lit';
46
+
47
+ class MyComponent extends HyperionLightElement {
48
+ /* ... */
49
+ }
50
+ ```
51
+
52
+ ## Exports
53
+
54
+ | Subpath | Purpose |
55
+ |---|---|
56
+ | `.` | Barrel: `tailwindPreset`, base Lit element, mixins |
57
+ | `./tailwind/preset` | Tailwind 3.x preset (semantic colours, spacing, typography) |
58
+ | `./tokens/*` | Raw CSS custom properties (`colors.css`, `spacing.css`, `typography.css`, `index.css`) |
59
+ | `./lit` / `./lit/*` | Base Lit element + mixins |
60
+ | `./html` | HTML sanitizer (allowlist) used for cookie and response HTML |
61
+
62
+ ## Requirements
63
+
64
+ A TypeScript-aware bundler (Vite, esbuild, webpack with `ts-loader`, etc.).
65
+ This package ships `.ts` source, not pre-compiled JavaScript, so it cannot be
66
+ loaded directly by Node.
67
+
68
+ ## Links
69
+
70
+ - Website: <https://hyperionfront.dev>
71
+ - Live demo: <https://demo.hyperionfront.dev>
72
+ - Repository: <https://github.com/magentofullstackdev/hyperion>
73
+ - Changelog: [`CHANGELOG.md`](https://github.com/magentofullstackdev/hyperion/blob/main/CHANGELOG.md) in the main repo
74
+ - Issues: <https://github.com/magentofullstackdev/hyperion/issues>
75
+ - Documentation: `docs/child-themes.md` in the main repo (design tokens, base element)
76
+
77
+ ## License
78
+
79
+ MIT, see [LICENSE](./LICENSE).
package/package.json CHANGED
@@ -1,6 +1,69 @@
1
1
  {
2
2
  "name": "@magentofullstackdev/hyperion-shared",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.9.0-beta.2",
4
+ "description": "Shared design tokens, Tailwind preset, and base Lit element/mixins for the Hyperion Magento 2 theme suite. Consumed by @magentofullstackdev/hyperion-theme and @magentofullstackdev/hyperion-checkout.",
5
+ "license": "MIT",
6
+ "author": "Sergiu Ro <sergiu.ro@magentofullstack.dev>",
7
+ "homepage": "https://hyperionfront.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/magentofullstackdev/hyperion.git",
11
+ "directory": "frontend/packages/shared"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/magentofullstackdev/hyperion/issues"
15
+ },
16
+ "keywords": [
17
+ "magento",
18
+ "magento2",
19
+ "hyperion",
20
+ "tailwind",
21
+ "tailwind-preset",
22
+ "lit",
23
+ "design-tokens",
24
+ "frontend"
25
+ ],
26
+ "type": "module",
27
+ "main": "./src/index.ts",
28
+ "types": "./src/index.ts",
29
+ "exports": {
30
+ ".": "./src/index.ts",
31
+ "./tokens/*": "./src/tokens/*",
32
+ "./tailwind/preset": "./src/tailwind/preset.ts",
33
+ "./lit": "./src/lit/index.ts",
34
+ "./lit/*": "./src/lit/*",
35
+ "./html": "./src/html/index.ts"
36
+ },
37
+ "files": [
38
+ "src",
39
+ "README.md",
40
+ "LICENSE",
41
+ "!src/**/__tests__",
42
+ "!src/**/*.test.*",
43
+ "!src/**/*.spec.*"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "dependencies": {
49
+ "@tailwindcss/typography": "^0.5.19"
50
+ },
51
+ "peerDependencies": {
52
+ "lit": "^3.1.2",
53
+ "tailwindcss": "^3.4.0"
54
+ },
55
+ "devDependencies": {
56
+ "@typescript-eslint/eslint-plugin": "^6.15.0",
57
+ "@typescript-eslint/parser": "^6.15.0",
58
+ "eslint": "^8.56.0",
59
+ "typescript": "^5.3.0"
60
+ },
61
+ "engines": {
62
+ "node": ">=22.0.0"
63
+ },
64
+ "scripts": {
65
+ "build": "echo \"@magentofullstackdev/hyperion-shared has no build step: consumed as TypeScript source by sibling workspaces\"",
66
+ "typecheck": "tsc --noEmit",
67
+ "lint": "eslint 'src/**/*.ts'"
68
+ }
6
69
  }
@@ -0,0 +1,12 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Sergiu Ro -- magentofullstackdev
3
+
4
+ export {
5
+ sanitizeHtml,
6
+ sanitizeMessageHtml,
7
+ htmlToText,
8
+ RICH_TEXT_TAGS,
9
+ MESSAGE_TAGS,
10
+ MESSAGE_OPTIONS,
11
+ } from './sanitize.js';
12
+ export type { SanitizeOptions } from './sanitize.js';
@@ -0,0 +1,156 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Sergiu Ro -- magentofullstackdev
3
+
4
+ /**
5
+ * Allowlist HTML sanitizer for the few places where Magento hands the
6
+ * storefront display HTML: session messages (the `mage-messages` cookie)
7
+ * and admin-authored rich text in the checkout.
8
+ *
9
+ * Not a general-purpose sanitizer. The input is parsed into an inert
10
+ * document (DOMParser: no script runs, no resource loads, no event
11
+ * handler fires) and the output is rebuilt node by node from the
12
+ * allowlist, so nothing that is not named here can reach the page.
13
+ * Attributes are dropped, except the listed ones on links.
14
+ */
15
+
16
+ export interface SanitizeOptions {
17
+ /** Element names kept in the output. Anything else is unwrapped to its children. */
18
+ tags?: readonly string[];
19
+ /** Attributes kept on `<a>`. */
20
+ linkAttributes?: readonly string[];
21
+ /** URL schemes (with the colon) a link may point to; relative links resolve to the page's own. */
22
+ linkProtocols?: readonly string[];
23
+ }
24
+
25
+ /** Inline formatting and lists, as Magento's rich-text editor emits them. */
26
+ export const RICH_TEXT_TAGS: readonly string[] = [
27
+ 'p', 'br', 'strong', 'em', 'b', 'i', 'u',
28
+ 'ul', 'ol', 'li',
29
+ 'a', 'span', 'div',
30
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
31
+ ];
32
+
33
+ /** What core's message component allows (Magento_Theme/js/view/messages.js). */
34
+ export const MESSAGE_TAGS: readonly string[] = ['div', 'span', 'b', 'strong', 'i', 'em', 'u', 'a'];
35
+
36
+ export const MESSAGE_OPTIONS: SanitizeOptions = {
37
+ tags: MESSAGE_TAGS,
38
+ linkAttributes: ['href'],
39
+ linkProtocols: ['http:', 'https:'],
40
+ };
41
+
42
+ const DEFAULT_LINK_ATTRIBUTES: readonly string[] = ['href', 'title', 'rel', 'target'];
43
+ const DEFAULT_LINK_PROTOCOLS: readonly string[] = ['http:', 'https:', 'mailto:', 'tel:'];
44
+
45
+ /** Elements whose content is code or foreign markup, never text to show. */
46
+ const DISCARDED_TAGS = new Set([
47
+ 'script', 'style', 'template', 'noscript', 'iframe', 'object', 'embed',
48
+ 'svg', 'math', 'textarea', 'title', 'head',
49
+ ]);
50
+
51
+ interface Rules {
52
+ tags: Set<string>;
53
+ linkAttributes: Set<string>;
54
+ linkProtocols: Set<string>;
55
+ }
56
+
57
+ function parse(input: string): { doc: Document; root: Element | null } {
58
+ const doc = new DOMParser().parseFromString(`<div>${input}</div>`, 'text/html');
59
+ return { doc, root: doc.body.firstElementChild };
60
+ }
61
+
62
+ /**
63
+ * The scheme is decided by the URL parser, not by a pattern: it is what
64
+ * the browser will use and it is immune to case and whitespace tricks.
65
+ */
66
+ function isSafeHref(href: string, protocols: Set<string>): boolean {
67
+ try {
68
+ return protocols.has(new URL(href, window.location.origin).protocol);
69
+ } catch {
70
+ return false;
71
+ }
72
+ }
73
+
74
+ function cleanLink(source: Element, clean: Element, rules: Rules): void {
75
+ for (const attr of Array.from(source.attributes)) {
76
+ const name = attr.name.toLowerCase();
77
+ if (rules.linkAttributes.has(name)) {
78
+ clean.setAttribute(name, attr.value);
79
+ }
80
+ }
81
+ const href = clean.getAttribute('href') ?? '';
82
+ if (href && !isSafeHref(href.trim(), rules.linkProtocols)) {
83
+ clean.removeAttribute('href');
84
+ }
85
+ const target = clean.getAttribute('target');
86
+ if (target !== null && target !== '_blank') {
87
+ clean.removeAttribute('target');
88
+ }
89
+ const safeHref = clean.getAttribute('href') ?? '';
90
+ if (/^https?:/i.test(safeHref) || clean.getAttribute('target') === '_blank') {
91
+ clean.setAttribute('rel', 'noopener noreferrer');
92
+ }
93
+ }
94
+
95
+ function appendClean(doc: Document, source: Node, target: Node, rules: Rules): void {
96
+ source.childNodes.forEach((child) => {
97
+ if (child.nodeType === 3) {
98
+ target.appendChild(doc.createTextNode(child.textContent ?? ''));
99
+ return;
100
+ }
101
+ if (child.nodeType !== 1) {
102
+ return;
103
+ }
104
+ const element = child as Element;
105
+ const tag = element.tagName.toLowerCase();
106
+ if (DISCARDED_TAGS.has(tag)) {
107
+ return;
108
+ }
109
+ if (!rules.tags.has(tag)) {
110
+ appendClean(doc, element, target, rules);
111
+ return;
112
+ }
113
+ const clean = doc.createElement(tag);
114
+ if (tag === 'a') {
115
+ cleanLink(element, clean, rules);
116
+ }
117
+ appendClean(doc, element, clean, rules);
118
+ target.appendChild(clean);
119
+ });
120
+ }
121
+
122
+ /**
123
+ * HTML that holds only the allowed elements; safe to assign to `innerHTML`.
124
+ */
125
+ export function sanitizeHtml(input: string, options: SanitizeOptions = {}): string {
126
+ const { doc, root } = parse(String(input ?? ''));
127
+ if (!root) return '';
128
+ const out = doc.createElement('div');
129
+ appendClean(doc, root, out, {
130
+ tags: new Set(options.tags ?? RICH_TEXT_TAGS),
131
+ linkAttributes: new Set(options.linkAttributes ?? DEFAULT_LINK_ATTRIBUTES),
132
+ linkProtocols: new Set(options.linkProtocols ?? DEFAULT_LINK_PROTOCOLS),
133
+ });
134
+ return out.innerHTML;
135
+ }
136
+
137
+ /**
138
+ * Session message from Magento as HTML: core's message allowlist, links
139
+ * to http(s) and relative targets only.
140
+ */
141
+ export function sanitizeMessageHtml(input: string): string {
142
+ return sanitizeHtml(input, MESSAGE_OPTIONS);
143
+ }
144
+
145
+ /**
146
+ * Plain text of a value Magento hands out as display HTML (messages, cart
147
+ * item option values: escaped text, list entries joined with `<br />`,
148
+ * bundle selections with the price in a `<span>`). Line breaks become `, `.
149
+ */
150
+ export function htmlToText(input: string): string {
151
+ const { doc, root } = parse(String(input ?? ''));
152
+ if (!root) return '';
153
+ root.querySelectorAll(Array.from(DISCARDED_TAGS).join(',')).forEach((element) => element.remove());
154
+ root.querySelectorAll('br').forEach((br) => br.replaceWith(doc.createTextNode(', ')));
155
+ return (root.textContent ?? '').replace(/\s+/g, ' ').replace(/ ,/g, ',').trim();
156
+ }
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Sergiu Ro -- magentofullstackdev
3
+
4
+ /**
5
+ * @magentofullstackdev/hyperion-shared barrel export.
6
+ *
7
+ * Re-exports the public API surface of the shared workspace package:
8
+ * Tailwind preset, base Lit element, mixins, HTML sanitizer. Design tokens (CSS) are
9
+ * consumed via direct CSS imports -- see `./tokens/*` exports in
10
+ * package.json.
11
+ */
12
+ export { default as tailwindPreset } from './tailwind/preset.js';
13
+ export * from './lit/index.js';
14
+ export * from './html/index.js';
@@ -0,0 +1,30 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Sergiu Ro -- magentofullstackdev
3
+
4
+ /**
5
+ * Base Lit element for Hyperion components that need light-DOM rendering.
6
+ *
7
+ * Several Hyperion components -- every form-bearing component in the
8
+ * checkout, the account-nav enhancer, the coupon form,
9
+ * etc. -- must render to light DOM so:
10
+ *
11
+ * * Tailwind utility classes from the page's stylesheet cascade in,
12
+ * * Browser autofill and password managers (1Password, Bitwarden,
13
+ * browser built-ins) can introspect the inputs,
14
+ * * `form.checkValidity()` and the Constraint Validation API cross
15
+ * the element boundary reliably.
16
+ *
17
+ * This base class collapses the boilerplate `createRenderRoot() { return this; }`
18
+ * that every such component would otherwise duplicate. Components that
19
+ * need shadow DOM (sliders, dropdowns, the mini-cart drawer) should
20
+ * extend `LitElement` directly -- they don't need this class.
21
+ */
22
+ import { LitElement } from 'lit';
23
+
24
+ export class HyperionLightElement extends LitElement {
25
+ public override createRenderRoot(): HTMLElement {
26
+ return this;
27
+ }
28
+ }
29
+
30
+ export type HyperionLightElementBase = typeof HyperionLightElement;
@@ -0,0 +1,13 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Sergiu Ro -- magentofullstackdev
3
+
4
+ /**
5
+ * @magentofullstackdev/hyperion-shared/lit barrel.
6
+ *
7
+ * Re-exports the Lit primitives shared across @magentofullstackdev/hyperion-theme
8
+ * and @magentofullstackdev/hyperion-checkout: a base element with the suite-wide
9
+ * light-DOM render-root convention, and mixins for SignalWatcher
10
+ * integration.
11
+ */
12
+ export { HyperionLightElement } from './HyperionLightElement.js';
13
+ export type { HyperionLightElementBase } from './HyperionLightElement.js';
@@ -0,0 +1,121 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Sergiu Ro -- magentofullstackdev
3
+
4
+ /**
5
+ * @magentofullstackdev/hyperion-shared/tailwind/preset
6
+ *
7
+ * Single source of truth for the Hyperion suite's Tailwind palette
8
+ * mapping. Both @magentofullstackdev/hyperion-theme and @magentofullstackdev/hyperion-checkout
9
+ * extend this preset (`presets: [hyperionPreset]`) so a `bg-primary` /
10
+ * `text-on-primary` / `border-subtle` class resolves identically in
11
+ * theme markup and checkout markup.
12
+ *
13
+ * Every semantic color token is mapped to a CSS Custom Property
14
+ * declared in `@magentofullstackdev/hyperion-shared/tokens/colors.css` using the
15
+ * `rgb(var(--color-*) / <alpha-value>)` syntax that lets Tailwind's
16
+ * opacity-modifier classes (e.g. `bg-primary/50`) work.
17
+ *
18
+ * `primary` and `primary-hover` are independent tokens so that
19
+ * `ring-primary` (focus-visibility) and `bg-primary-hover` (hover)
20
+ * resolve to separate CSS variables -- satisfies WCAG 2.1 AA
21
+ * focus-visibility overridability.
22
+ *
23
+ * The `content` array is intentionally EMPTY here -- each consuming
24
+ * package declares its own `content` glob in its `tailwind.config.ts`
25
+ * because the paths are package-specific.
26
+ */
27
+ import typography from '@tailwindcss/typography';
28
+ import type { Config } from 'tailwindcss';
29
+
30
+ const preset: Partial<Config> = {
31
+ theme: {
32
+ extend: {
33
+ colors: {
34
+ primary: 'rgb(var(--color-primary) / <alpha-value>)',
35
+ 'primary-hover': 'rgb(var(--color-primary-hover) / <alpha-value>)',
36
+ secondary: 'rgb(var(--color-secondary) / <alpha-value>)',
37
+ accent: 'rgb(var(--color-accent) / <alpha-value>)',
38
+ surface: 'rgb(var(--color-surface) / <alpha-value>)',
39
+ 'surface-raised': 'rgb(var(--color-surface-raised) / <alpha-value>)',
40
+ 'on-primary': 'rgb(var(--color-on-primary) / <alpha-value>)',
41
+ 'on-secondary': 'rgb(var(--color-on-secondary) / <alpha-value>)',
42
+ muted: 'rgb(var(--color-muted) / <alpha-value>)',
43
+ subtle: 'rgb(var(--color-subtle) / <alpha-value>)',
44
+ error: 'rgb(var(--color-error) / <alpha-value>)',
45
+ 'on-error': 'rgb(var(--color-on-error) / <alpha-value>)',
46
+ 'error-strong': 'rgb(var(--color-error-strong) / <alpha-value>)',
47
+ success: 'rgb(var(--color-success) / <alpha-value>)',
48
+ 'on-success': 'rgb(var(--color-on-success) / <alpha-value>)',
49
+ 'success-strong': 'rgb(var(--color-success-strong) / <alpha-value>)',
50
+ warning: 'rgb(var(--color-warning) / <alpha-value>)',
51
+ 'warning-strong': 'rgb(var(--color-warning-strong) / <alpha-value>)',
52
+ 'on-warning': 'rgb(var(--color-on-warning) / <alpha-value>)',
53
+ info: 'rgb(var(--color-info) / <alpha-value>)',
54
+ 'on-info': 'rgb(var(--color-on-info) / <alpha-value>)',
55
+ inverted: 'rgb(var(--color-surface-inverted) / <alpha-value>)',
56
+ 'on-inverted': 'rgb(var(--color-on-inverted) / <alpha-value>)',
57
+ 'on-inverted-muted': 'rgb(var(--color-on-inverted-muted) / <alpha-value>)',
58
+ 'subtle-inverted': 'rgb(var(--color-subtle-inverted) / <alpha-value>)',
59
+ 'price-sale': 'rgb(var(--color-price-sale) / <alpha-value>)',
60
+ // Extended tokens: semantic replacements for the banned palette classes.
61
+ 'surface-sunken': 'rgb(var(--color-surface-sunken) / <alpha-value>)',
62
+ 'surface-overlay': 'rgb(var(--color-surface-overlay) / <alpha-value>)',
63
+ 'text-default': 'rgb(var(--color-text-default) / <alpha-value>)',
64
+ 'text-secondary': 'rgb(var(--color-text-secondary) / <alpha-value>)',
65
+ 'text-tertiary': 'rgb(var(--color-text-tertiary) / <alpha-value>)',
66
+ 'border-default': 'rgb(var(--color-border-default) / <alpha-value>)',
67
+ divider: 'rgb(var(--color-divider) / <alpha-value>)',
68
+ 'error-hover': 'rgb(var(--color-error-hover) / <alpha-value>)',
69
+ 'error-active': 'rgb(var(--color-error-active) / <alpha-value>)',
70
+ 'success-subtle': 'rgb(var(--color-success-subtle) / <alpha-value>)',
71
+ 'warning-light': 'rgb(var(--color-warning-light) / <alpha-value>)',
72
+ 'focus-ring': 'rgb(var(--color-focus-ring) / <alpha-value>)',
73
+ // Checkout aliases -- kept in the preset so existing
74
+ // checkout component class names (`bg-brand`, `text-on-brand`)
75
+ // keep resolving without a per-component rewrite.
76
+ brand: 'rgb(var(--checkout-color-brand) / <alpha-value>)',
77
+ 'on-brand': 'rgb(var(--checkout-color-on-brand) / <alpha-value>)',
78
+ danger: 'rgb(var(--checkout-color-danger) / <alpha-value>)',
79
+ 'on-danger': 'rgb(var(--checkout-color-on-danger) / <alpha-value>)',
80
+ },
81
+ typography: () => ({
82
+ DEFAULT: {
83
+ css: {
84
+ '--tw-prose-body': 'rgb(var(--color-secondary))',
85
+ '--tw-prose-headings': 'rgb(var(--color-secondary))',
86
+ '--tw-prose-lead': 'rgb(var(--color-muted))',
87
+ '--tw-prose-links': 'rgb(var(--color-primary))',
88
+ '--tw-prose-bold': 'rgb(var(--color-secondary))',
89
+ '--tw-prose-counters': 'rgb(var(--color-muted))',
90
+ '--tw-prose-bullets': 'rgb(var(--color-subtle))',
91
+ '--tw-prose-hr': 'rgb(var(--color-subtle))',
92
+ '--tw-prose-quotes': 'rgb(var(--color-secondary))',
93
+ '--tw-prose-quote-borders': 'rgb(var(--color-primary))',
94
+ '--tw-prose-captions': 'rgb(var(--color-muted))',
95
+ '--tw-prose-code': 'rgb(var(--color-secondary))',
96
+ '--tw-prose-pre-code': 'rgb(var(--color-on-inverted))',
97
+ '--tw-prose-pre-bg': 'rgb(var(--color-surface-inverted))',
98
+ '--tw-prose-th-borders': 'rgb(var(--color-subtle))',
99
+ '--tw-prose-td-borders': 'rgb(var(--color-subtle))',
100
+ maxWidth: 'none',
101
+ a: {
102
+ fontWeight: '500',
103
+ textDecoration: 'underline',
104
+ textUnderlineOffset: '2px',
105
+ '&:hover': {
106
+ color: 'rgb(var(--color-primary-hover))',
107
+ },
108
+ },
109
+ 'h1, h2, h3, h4': {
110
+ fontWeight: '700',
111
+ letterSpacing: '-0.01em',
112
+ },
113
+ },
114
+ },
115
+ }),
116
+ },
117
+ },
118
+ plugins: [typography],
119
+ };
120
+
121
+ export default preset;
@@ -0,0 +1,105 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /* Copyright (c) 2026 Sergiu Ro -- magentofullstackdev */
3
+
4
+ /*
5
+ * @magentofullstackdev/hyperion-shared -- semantic color tokens.
6
+ *
7
+ * Single source of truth for the Hyperion suite's palette. Both
8
+ * @magentofullstackdev/hyperion-theme and @magentofullstackdev/hyperion-checkout import this
9
+ * file (via `@magentofullstackdev/hyperion-shared/tokens/colors.css`) so a single rebrand
10
+ * propagates everywhere.
11
+ *
12
+ * Values MUST be raw RGB channel triplets as space-separated integers
13
+ * (e.g. `37 99 235`) -- never hex, never `rgb()` wrappers. This is the
14
+ * only format that lets Tailwind's `rgb(var(--color-*) / <alpha-value>)`
15
+ * mapping produce valid CSS for opacity-modifier classes such as
16
+ * `bg-primary/50`.
17
+ *
18
+ * Child themes override these declarations in their own `_theme.css`
19
+ * (loaded after this file in the cascade) -- see THEMING_GUIDE.md.
20
+ */
21
+ :root {
22
+ /* --- Primary brand color -- buttons, links, active states, focus rings --- */
23
+ --color-primary: 37 99 235; /* #2563eb */
24
+ --color-primary-hover: 29 78 216; /* #1d4ed8 */
25
+
26
+ /* --- Secondary / supporting color --- */
27
+ --color-secondary: 100 116 139; /* #64748b */
28
+
29
+ /* --- Accent / highlight color --- */
30
+ --color-accent: 245 158 11; /* #f59e0b */
31
+
32
+ /* --- Surface backgrounds --- */
33
+ --color-surface: 255 255 255; /* #ffffff */
34
+ --color-surface-raised: 249 250 251; /* #f9fafb */
35
+
36
+ /* --- Text on colored backgrounds --- */
37
+ --color-on-primary: 255 255 255; /* #ffffff */
38
+ --color-on-secondary: 255 255 255; /* #ffffff */
39
+
40
+ /* --- Body text variants --- */
41
+ --color-muted: 107 114 128; /* #6b7280 */
42
+ --color-subtle: 229 231 235; /* #e5e7eb -- borders and dividers */
43
+
44
+ /* --- Semantic state colors --- */
45
+ --color-error: 220 38 38; /* #dc2626 */
46
+ --color-on-error: 255 255 255; /* #ffffff */
47
+ --color-error-strong: 185 28 28; /* #b91c1c, red-700 -- error TEXT on the bg-error/10 tint: 6.47:1 on white, 5.54:1 on the tint (the error red itself measured 4.13:1 there) */
48
+ --color-success: 21 128 61; /* #15803d, green-700: 5.02:1 on white, 4.57:1 on the success-subtle toast (axe flagged green-600 at 3.3:1) */
49
+ --color-on-success: 255 255 255; /* #ffffff */
50
+ --color-success-strong: 22 101 52; /* #166534, green-800 -- success TEXT on the bg-success/10 tint: 7.13:1 on white, 6.23:1 on the tint (green-700 measured 4.38:1 there) */
51
+ --color-warning: 217 119 6; /* #d97706 -- amber for validation / soft-fail: borders, icons, badges */
52
+ --color-warning-strong: 180 83 9; /* #b45309, amber-700 -- warning TEXT: 5.02:1 on white, 4.50:1 on the bg-warning/10 tint (amber-600 measured 2.86:1 on the "Only N left" pill, axe serious) */
53
+ --color-on-warning: 255 255 255; /* #ffffff */
54
+ --color-info: 37 99 235; /* #2563eb -- same as primary by default */
55
+ --color-on-info: 255 255 255; /* #ffffff */
56
+
57
+ /* --- Pricing tokens --- */
58
+ /* Color of the active "special" / final price on discounted items.
59
+ Defaults to the error red so the discount reads immediately; a
60
+ store can remap to `--color-primary` or a bespoke sale-hot-pink
61
+ without touching any .phtml. */
62
+ --color-price-sale: var(--color-error);
63
+
64
+ /* --- Extended tokens: secondary surface + text scale + helpers.
65
+ Each replaces an absolute palette class (banned in the theme) so every
66
+ color decision still resolves through a custom property. */
67
+ --color-surface-sunken: 248 250 252; /* #f8fafc -- slate-50, sub-page background blocks */
68
+ --color-surface-overlay: 241 245 249; /* #f1f5f9 -- modal/scrim backdrop */
69
+ --color-text-default: 17 24 39; /* #111827 -- primary body copy */
70
+ --color-text-secondary: 55 65 81; /* #374151 -- supporting copy */
71
+ --color-text-tertiary: 107 114 128; /* #6b7280 -- captions, muted helpers */
72
+ --color-border-default: 229 231 235; /* #e5e7eb */
73
+ --color-divider: 243 244 246; /* #f3f4f6 -- table row separators */
74
+ --color-error-hover: 220 38 38; /* #dc2626 -- destructive hover */
75
+ --color-error-active: 185 28 28; /* #b91c1c -- destructive pressed */
76
+ --color-success-subtle: 220 252 231; /* #dcfce7 -- success toast bg */
77
+ --color-warning-light: 253 224 71; /* #fde047 -- group-hover star icon */
78
+ --color-focus-ring: 99 102 241; /* #6366f1 -- focus ring */
79
+
80
+ /* --- Inverted surface (dark footer, cookie banner) --- */
81
+ /* An inverted surface is a dark band (typically the footer) with
82
+ light text and muted-light secondary text. A child theme can
83
+ redefine the pair without touching markup. */
84
+ --color-surface-inverted: 17 24 39; /* #111827 */
85
+ --color-on-inverted: 229 231 235; /* #e5e7eb */
86
+ --color-on-inverted-muted: 156 163 175; /* #9ca3af */
87
+ --color-subtle-inverted: 55 65 81; /* #374151 -- dividers inside dark surfaces */
88
+
89
+ /* --- Checkout aliases --- */
90
+ /* The checkout package reads --checkout-color-* tokens (its
91
+ Tailwind config in frontend/packages/module-checkout). Alias them
92
+ to the semantic tokens above so the checkout bundle inherits the store
93
+ look without a rebuild. Override in a child theme to give the
94
+ checkout a distinct visual identity from the rest of the store. */
95
+ --checkout-color-brand: var(--color-secondary);
96
+ --checkout-color-accent: var(--color-primary);
97
+ --checkout-color-danger: var(--color-error);
98
+ --checkout-color-muted: var(--color-muted);
99
+ --checkout-color-surface: var(--color-surface);
100
+ --checkout-color-surface-raised: var(--color-surface-raised);
101
+ --checkout-color-on-brand: var(--color-on-primary);
102
+ --checkout-color-on-accent: var(--color-on-primary);
103
+ --checkout-color-on-danger: var(--color-on-error);
104
+ --checkout-color-subtle: var(--color-subtle);
105
+ }
@@ -0,0 +1,13 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /* Copyright (c) 2026 Sergiu Ro -- magentofullstackdev */
3
+
4
+ /*
5
+ * @magentofullstackdev/hyperion-shared -- design-token barrel.
6
+ *
7
+ * Imported by both @magentofullstackdev/hyperion-theme (via web/css/source/_theme.css)
8
+ * and @magentofullstackdev/hyperion-checkout (via src/styles/vars.css). All Hyperion
9
+ * Composer packages render against the same semantic palette.
10
+ */
11
+ @import "./colors.css";
12
+ @import "./typography.css";
13
+ @import "./spacing.css";
@@ -0,0 +1,14 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /* Copyright (c) 2026 Sergiu Ro -- magentofullstackdev */
3
+
4
+ /*
5
+ * @magentofullstackdev/hyperion-shared -- spacing tokens.
6
+ *
7
+ * Section-level rhythm for theme chrome and content surfaces. Component-
8
+ * specific spacing (slider gap, swatch size, panel width, etc.) lives
9
+ * in the consuming package because it is component-specific, not part
10
+ * of the global design contract.
11
+ */
12
+ :root {
13
+ --spacing-section: 2rem;
14
+ }
@@ -0,0 +1,20 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /* Copyright (c) 2026 Sergiu Ro -- magentofullstackdev */
3
+
4
+ /*
5
+ * @magentofullstackdev/hyperion-shared -- typography tokens.
6
+ *
7
+ * Single source of truth for type-scale and font stacks across the
8
+ * Hyperion suite. Override in a child theme's `_theme.css` to swap the
9
+ * font stack without touching markup.
10
+ */
11
+ :root {
12
+ --font-family-base: ui-sans-serif, system-ui, sans-serif;
13
+ --font-size-base: 1rem;
14
+
15
+ /* --- Checkout font alias --- */
16
+ /* The checkout package reads --checkout-font-sans (its Tailwind
17
+ config in frontend/packages/module-checkout). Alias to the suite
18
+ font so the checkout inherits the store typography by default. */
19
+ --checkout-font-sans: var(--font-family-base);
20
+ }