@aglyn/aglyn-node-renderer 1.0.0-beta.172 → 1.0.0-beta.173
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/aglyn-node-renderer",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.173",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"./package.json": "./package.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
28
|
-
"@aglyn/shared-data-types": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-ui-theme": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-util-tools": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-util-vendor": "1.0.0-beta.
|
|
27
|
+
"@aglyn/aglyn": "1.0.0-beta.173",
|
|
28
|
+
"@aglyn/shared-data-types": "1.0.0-beta.173",
|
|
29
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.173",
|
|
30
|
+
"@aglyn/shared-ui-theme": "1.0.0-beta.173",
|
|
31
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.173",
|
|
32
|
+
"@aglyn/shared-util-vendor": "1.0.0-beta.173",
|
|
33
33
|
"mobx-react-lite": "^4.1.1",
|
|
34
34
|
"react-is": "^19.2.8"
|
|
35
35
|
},
|
|
@@ -29,13 +29,14 @@ import { NODE_HIDE_IF_PROP, NODE_HIDE_UNLESS_PROP } from "@aglyn/aglyn/app-utils
|
|
|
29
29
|
import { NODE_ANIMATION_DELAY_PROP, NODE_ANIMATION_DURATION_PROP, NODE_ANIMATION_EASE_PROP, NODE_ANIMATION_PROP, NODE_ANIMATION_REPEAT_PROP, NODE_ANIMATION_STAGGER_PROP, NODE_ANIMATION_STAGGER_STEP_PROP, NODE_ANIMATION_TRIGGER_PROP, resolveElementAnimation } from "@aglyn/aglyn/app-utils/element-animation";
|
|
30
30
|
import { EnabledPluginsContext, isSwitchedOffForRenderedSite } from "@aglyn/aglyn/app-utils/enabled-plugins-context";
|
|
31
31
|
import { NodeIdentityContext } from "@aglyn/aglyn/app-utils/node-identity";
|
|
32
|
+
import { NODE_COLOR_SCHEME_PROP, resolveElementColorScheme } from "@aglyn/aglyn/app-utils/element-color-scheme";
|
|
32
33
|
import { FEATURE_FLAG } from "@aglyn/aglyn/foundation/constants/shared";
|
|
33
34
|
// Deep import, NOT the barrel: `@aglyn/shared-ui-jsx`'s index re-exports the
|
|
34
35
|
// Pages Router hooks (`next/router`), the inline SVG icon set and the whole
|
|
35
36
|
// ~12,000-module MDI catalog, none of which a rendered node needs. This file
|
|
36
37
|
// is on every published page, so the barrel's reach is that page's reach.
|
|
37
38
|
import { AglynText } from "@aglyn/shared-ui-jsx/components/aglyn-text";
|
|
38
|
-
import { styled, useTheme } from "@aglyn/shared-ui-theme";
|
|
39
|
+
import { styled, ThemeProvider, useSiteSchemeThemes, useTheme } from "@aglyn/shared-ui-theme";
|
|
39
40
|
import { mergeSxProps } from "@aglyn/shared-ui-theme";
|
|
40
41
|
import { observer } from "mobx-react-lite";
|
|
41
42
|
import { forwardRef, useContext } from "react";
|
|
@@ -46,7 +47,7 @@ import { resolvePaletteVarsSx, resolveSchemeSx } from "../utils/scheme-sx.js";
|
|
|
46
47
|
const DefaultComponent = styled('div')({});
|
|
47
48
|
export const Leaf = observer(/*#__PURE__*/ forwardRef((props, ref)=>{
|
|
48
49
|
var _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
|
|
49
|
-
var _schema_flags, _theme_palette, _schema_flags1;
|
|
50
|
+
var _schema_flags, _theme_palette, _forcedTheme_palette, _schema_flags1;
|
|
50
51
|
const { children, node, sx, className, style } = props, rest = _object_without_properties_loose(props, [
|
|
51
52
|
"children",
|
|
52
53
|
"node",
|
|
@@ -72,7 +73,9 @@ export const Leaf = observer(/*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
72
73
|
// `none` case is stripped too (it resolves to no animation, but it is
|
|
73
74
|
// still a prop an author saved) and so the props object keeps one
|
|
74
75
|
// shape.
|
|
75
|
-
[NODE_ANIMATION_PROP]: _animation, [NODE_ANIMATION_TRIGGER_PROP]: _animationTrigger, [NODE_ANIMATION_DURATION_PROP]: _animationDuration, [NODE_ANIMATION_DELAY_PROP]: _animationDelay, [NODE_ANIMATION_REPEAT_PROP]: _animationRepeat, [NODE_ANIMATION_EASE_PROP]: _animationEase, [NODE_ANIMATION_STAGGER_PROP]: _animationStagger, [NODE_ANIMATION_STAGGER_STEP_PROP]: _animationStaggerStep
|
|
76
|
+
[NODE_ANIMATION_PROP]: _animation, [NODE_ANIMATION_TRIGGER_PROP]: _animationTrigger, [NODE_ANIMATION_DURATION_PROP]: _animationDuration, [NODE_ANIMATION_DELAY_PROP]: _animationDelay, [NODE_ANIMATION_REPEAT_PROP]: _animationRepeat, [NODE_ANIMATION_EASE_PROP]: _animationEase, [NODE_ANIMATION_STAGGER_PROP]: _animationStagger, [NODE_ANIMATION_STAGGER_STEP_PROP]: _animationStaggerStep, // A pinned color scheme (AGL-3284) is a directive to the renderer, like
|
|
77
|
+
// the two groups above: consumed below, never handed to the component.
|
|
78
|
+
[NODE_COLOR_SCHEME_PROP]: _colorScheme } = _ref6, resolvedProps = _object_without_properties_loose(_ref6, [
|
|
76
79
|
"sx",
|
|
77
80
|
"className",
|
|
78
81
|
"style",
|
|
@@ -85,7 +88,8 @@ export const Leaf = observer(/*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
85
88
|
NODE_ANIMATION_REPEAT_PROP,
|
|
86
89
|
NODE_ANIMATION_EASE_PROP,
|
|
87
90
|
NODE_ANIMATION_STAGGER_PROP,
|
|
88
|
-
NODE_ANIMATION_STAGGER_STEP_PROP
|
|
91
|
+
NODE_ANIMATION_STAGGER_STEP_PROP,
|
|
92
|
+
NODE_COLOR_SCHEME_PROP
|
|
89
93
|
].map(_to_property_key));
|
|
90
94
|
// Resolves to a class, a `data-` attribute and two custom properties; the
|
|
91
95
|
// keyframes themselves live in the tenant's stylesheet, so this costs no
|
|
@@ -142,6 +146,28 @@ export const Leaf = observer(/*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
142
146
|
// palette mode — the one signal that is correct in both places.
|
|
143
147
|
const theme = useTheme();
|
|
144
148
|
const activeScheme = (theme == null ? void 0 : (_theme_palette = theme.palette) == null ? void 0 : _theme_palette.mode) === 'dark' ? 'dark' : 'light';
|
|
149
|
+
// "Always light" / "Always dark" (AGL-3284). When the pinned scheme is not
|
|
150
|
+
// the active one, the element re-renders itself under the site's theme
|
|
151
|
+
// for that scheme, so its OWN sx — not only its descendants' — resolves
|
|
152
|
+
// palette tokens and `@scheme dark` slices for the pinned scheme. The
|
|
153
|
+
// inner render then sees the pinned scheme as active and takes the plain
|
|
154
|
+
// path; the mode check below is what guarantees that, because a site with
|
|
155
|
+
// one theme for both schemes (a single `fallback`) hands back a theme
|
|
156
|
+
// whose mode never changes, and re-wrapping it would never terminate.
|
|
157
|
+
// No provider (an email render, a bare test) means nothing to force.
|
|
158
|
+
// Every hook above runs on both paths, so the early return keeps the
|
|
159
|
+
// hook order stable when an author flips the setting.
|
|
160
|
+
const pinnedScheme = resolveElementColorScheme(_colorScheme);
|
|
161
|
+
const schemeThemes = useSiteSchemeThemes();
|
|
162
|
+
const forcedTheme = pinnedScheme && pinnedScheme !== activeScheme && schemeThemes ? schemeThemes(pinnedScheme) : undefined;
|
|
163
|
+
if (forcedTheme && ((_forcedTheme_palette = forcedTheme.palette) == null ? void 0 : _forcedTheme_palette.mode) === pinnedScheme) {
|
|
164
|
+
return /*#__PURE__*/ _jsx(ThemeProvider, {
|
|
165
|
+
theme: forcedTheme,
|
|
166
|
+
children: /*#__PURE__*/ _jsx(Leaf, _extends({}, props, {
|
|
167
|
+
ref: ref
|
|
168
|
+
}))
|
|
169
|
+
});
|
|
170
|
+
}
|
|
145
171
|
// MUI array composition: later entries win on key conflicts, so the
|
|
146
172
|
// node-level sx (Styles panel output) overrides props.sx.
|
|
147
173
|
//
|
|
@@ -169,8 +195,21 @@ export const Leaf = observer(/*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
169
195
|
// and the scheme pass above is what collapses a dark-scheme slice down
|
|
170
196
|
// into that same top level. Running it earlier would leave a dark
|
|
171
197
|
// override's font size unpinned.
|
|
198
|
+
//
|
|
199
|
+
// A pinned element paints its scheme's page background and text color
|
|
200
|
+
// (AGL-3284), UNDER every other style so an author's own background wins.
|
|
201
|
+
// Without it an "Always dark" band with no background of its own is
|
|
202
|
+
// light text on the light page behind it, and text that sets no color
|
|
203
|
+
// inherits the page's dark body color. `color-scheme` makes the browser's
|
|
204
|
+
// own controls and scrollbars inside the band match. Only a pinned
|
|
205
|
+
// element carries this, so an unpinned one renders exactly as before —
|
|
206
|
+
// and so does a pinned one on a surface with no site themes to pin to.
|
|
172
207
|
const authorSx = sanitizeAuthorSx(node == null ? void 0 : node.sx);
|
|
173
|
-
const composedSx = pinRampedTypographySx(resolvePaletteVarsSx(resolveSchemeSx(
|
|
208
|
+
const composedSx = pinRampedTypographySx(resolvePaletteVarsSx(resolveSchemeSx(pinnedScheme && schemeThemes ? mergeSxProps({
|
|
209
|
+
colorScheme: pinnedScheme,
|
|
210
|
+
color: 'text.primary',
|
|
211
|
+
bgcolor: 'background.default'
|
|
212
|
+
}, sx, propsSx, authorSx) : mergeSxProps(sx, propsSx, authorSx), activeScheme), theme == null ? void 0 : theme.palette));
|
|
174
213
|
/**
|
|
175
214
|
* Author visibility — the eye on the hierarchy row.
|
|
176
215
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn-node-renderer/src/lib/components/leaf.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Type-only, with every value this file reads named below (AGL-2486's rule,\n// applied to the render path's hottest file): a VALUE namespace import of the\n// core barrel is opaque to a bundler — it cannot know which exports are read,\n// so every module the barrel reaches is pinned into the published page's first\n// load.\nimport type * as Aglyn from '@aglyn/aglyn'\nimport { components } from '@aglyn/aglyn/aglyn'\nimport { sanitizeAuthorSx } from '@aglyn/aglyn/app-utils/author-css'\nimport { pinRampedTypographySx } from '@aglyn/aglyn/app-utils/responsive-typography-sx'\nimport {\n NODE_HIDE_IF_PROP,\n NODE_HIDE_UNLESS_PROP,\n} from '@aglyn/aglyn/app-utils/reusable-component-keys'\nimport {\n NODE_ANIMATION_DELAY_PROP,\n NODE_ANIMATION_DURATION_PROP,\n NODE_ANIMATION_EASE_PROP,\n NODE_ANIMATION_PROP,\n NODE_ANIMATION_REPEAT_PROP,\n NODE_ANIMATION_STAGGER_PROP,\n NODE_ANIMATION_STAGGER_STEP_PROP,\n NODE_ANIMATION_TRIGGER_PROP,\n resolveElementAnimation,\n} from '@aglyn/aglyn/app-utils/element-animation'\nimport {\n EnabledPluginsContext,\n isSwitchedOffForRenderedSite,\n} from '@aglyn/aglyn/app-utils/enabled-plugins-context'\nimport { NodeIdentityContext } from '@aglyn/aglyn/app-utils/node-identity'\nimport { FEATURE_FLAG } from '@aglyn/aglyn/foundation/constants/shared'\n// Deep import, NOT the barrel: `@aglyn/shared-ui-jsx`'s index re-exports the\n// Pages Router hooks (`next/router`), the inline SVG icon set and the whole\n// ~12,000-module MDI catalog, none of which a rendered node needs. This file\n// is on every published page, so the barrel's reach is that page's reach.\nimport { AglynText } from '@aglyn/shared-ui-jsx/components/aglyn-text'\nimport { styled, useTheme } from '@aglyn/shared-ui-theme'\nimport { mergeSxProps } from '@aglyn/shared-ui-theme'\nimport { observer } from 'mobx-react-lite'\nimport { forwardRef, type HTMLAttributes, useContext } from 'react'\nimport { isValidElementType } from 'react-is'\nimport RendererComponents from '../contexts/renderer-components'\nimport { LeafSxTransformContext } from '../contexts/leaf-sx-transform'\nimport { resolvePaletteVarsSx, resolveSchemeSx } from '../utils/scheme-sx'\n\nconst DefaultComponent = styled('div')({})\n\nexport interface LeafProps extends HTMLAttributes<any> {\n children?: any\n node: Aglyn.NodeSchema\n sx?: JSX.SxProps\n}\n\nexport const Leaf = observer(\n forwardRef<any, LeafProps>((props, ref) => {\n const { children, node, sx, className, style, ...rest } = props\n\n // Pull sx/className/style out of the node's props so the spreads below\n // can never clobber the merged values composed explicitly afterwards\n // (AGL-569: `props.sx` used to overwrite the node-level sx entirely).\n //\n // The visibility directives (AGL-1314) come out here too. The compose\n // step consumes and strips them, so a rendered page never carries one —\n // but the component EDITOR renders definition nodes ungrafted, on\n // purpose (the author has to see and select the part a page will hide),\n // and there the raw `hideIf` would spread onto the element as an\n // unknown `hideif` DOM attribute.\n const {\n sx: propsSx,\n className: propsClassName,\n style: propsStyle,\n [NODE_HIDE_IF_PROP]: _hideIf,\n [NODE_HIDE_UNLESS_PROP]: _hideUnless,\n // Element animation (AGL-2486): the reserved animation props come\n // out here for the same reason the visibility directives above do —\n // they are directives to the RENDERER, and spreading them onto the\n // element would land `aglynanimation=\"slide-up\"` as an unknown DOM\n // attribute. Destructured rather than `delete`d after the fact so the\n // `none` case is stripped too (it resolves to no animation, but it is\n // still a prop an author saved) and so the props object keeps one\n // shape.\n [NODE_ANIMATION_PROP]: _animation,\n [NODE_ANIMATION_TRIGGER_PROP]: _animationTrigger,\n [NODE_ANIMATION_DURATION_PROP]: _animationDuration,\n [NODE_ANIMATION_DELAY_PROP]: _animationDelay,\n [NODE_ANIMATION_REPEAT_PROP]: _animationRepeat,\n [NODE_ANIMATION_EASE_PROP]: _animationEase,\n [NODE_ANIMATION_STAGGER_PROP]: _animationStagger,\n [NODE_ANIMATION_STAGGER_STEP_PROP]: _animationStaggerStep,\n ...resolvedProps\n } = (node?.resolvedProps ?? node?.props ?? {}) as Record<string, any>\n\n // Resolves to a class, a `data-` attribute and two custom properties; the\n // keyframes themselves live in the tenant's stylesheet, so this costs no\n // JS on any surface. The besigner canvas never ships that stylesheet\n // (same posture as the AGL-562 hidden class), so an author sees the\n // element in its normal, selectable, un-animated state while editing.\n const animation = resolveElementAnimation({\n [NODE_ANIMATION_PROP]: _animation,\n [NODE_ANIMATION_TRIGGER_PROP]: _animationTrigger,\n [NODE_ANIMATION_DURATION_PROP]: _animationDuration,\n [NODE_ANIMATION_DELAY_PROP]: _animationDelay,\n [NODE_ANIMATION_REPEAT_PROP]: _animationRepeat,\n [NODE_ANIMATION_EASE_PROP]: _animationEase,\n [NODE_ANIMATION_STAGGER_PROP]: _animationStagger,\n [NODE_ANIMATION_STAGGER_STEP_PROP]: _animationStaggerStep,\n })\n // A component whose first-party plugin does not run on the rendered site\n // is drawn exactly as an unregistered one is (AGL-3033): the registry is\n // process-global and outlives the site that loaded the bundle, and the\n // site's own browser never loads it. Its schema goes with it, so the\n // void-element and positional flags cannot tell the server a different\n // story from the client either.\n const enabledPlugins = useContext(EnabledPluginsContext)\n const registeredSchema = components.getSchema(node?.componentId)\n const offForSite = isSwitchedOffForRenderedSite(\n registeredSchema?.pluginId,\n enabledPlugins,\n )\n const Factory = offForSite ? undefined : components.getFactory(node?.componentId)\n const Component = isValidElementType(Factory) ? Factory : DefaultComponent\n\n // Self-closing components (AGL-579): a component whose schema flags it\n // selfClosing renders a void DOM element (e.g. Image -> <img>), and React\n // throws during SSR when ANY children value reaches one — even the empty\n // `[undefined, false]` the JSX below always produces. Rendering the whole\n // page 500s off one image node (blog covers, AGL-579), so honor the flag\n // here: no JSX children, and strip a stray `children` prop too.\n const schema = offForSite ? undefined : registeredSchema\n const selfClosing = Boolean(\n (schema?.flags?.selfClosing ?? 0) & FEATURE_FLAG.ENABLED,\n )\n if (selfClosing) delete resolvedProps['children']\n\n const textContent = selfClosing ? null : resolvedProps?.['children']\n\n const mergedClassName =\n [propsClassName, node?.className, className, animation?.className]\n .filter(Boolean)\n .join(' ') || undefined\n // The animation's custom properties go in FIRST so an author who typed\n // `--aglyn-anim-duration` into the Custom CSS tab still wins.\n const mergedStyle =\n animation || propsStyle || style\n ? { ...animation?.style, ...propsStyle, ...style }\n : undefined\n\n // Canvas-only hook (AGL-581): the besigner provides a transform that\n // re-targets viewport media queries at the artboard device width.\n // Undefined everywhere else, keeping the tenant path unchanged.\n const transformSx = useContext(LeafSxTransformContext)\n // Scheme-scoped styles (AGL-588): sites swap a single-mode theme for\n // light/dark (tenant HostThemeProvider, canvas useAglynSiteTheme), so\n // '@scheme dark' sx slices resolve here against the ACTIVE theme's\n // palette mode — the one signal that is correct in both places.\n const theme = useTheme() as {\n palette?: { mode?: string } & Record<string, unknown>\n } | null\n const activeScheme = theme?.palette?.mode === 'dark' ? 'dark' : 'light'\n // MUI array composition: later entries win on key conflicts, so the\n // node-level sx (Styles panel output) overrides props.sx.\n //\n // Palette token references (AGL-1331): the Background Fill field\n // persists a token-bound gradient stop as\n // `var(--mui-palette-primary-main, #00B0FF)`, because `backgroundImage`\n // is NOT one of the sx keys MUI resolves against the palette. They are\n // substituted here, against the site theme, so the canvas cannot pick\n // up the console's `--mui-palette-*` and the tenant (whose theme has no\n // CSS variables at all) still tracks palette changes. Values carrying\n // no reference come back by identity.\n // Author CSS (AGL-1725): `node.sx` is the Styles panel's output, and it\n // is free text — `backgroundImage` is a first-class field and the Custom\n // CSS tab is free-solo, so any property and any value can be typed. On a\n // published site that lands in the visitor's document as a real `url()`,\n // which no input validator and no lint rule can see. Scrubbed HERE, at\n // the last point before the merge, so it also catches values already\n // stored; `sx` and `props.sx` are OUR components' own styles and are\n // deliberately left alone. The scrub is scheme-only and returns its\n // input by identity when nothing is refused, so the overwhelmingly\n // common case (no `url()` at all) costs one walk and no new object.\n // Responsive type ramp: LAST of the three sx passes, and it has to be —\n // it moves a scalar `fontSize` into the `xs` slice so the author's\n // explicit size sorts after the variant's `responsiveFontSizes` at-rules,\n // and the scheme pass above is what collapses a dark-scheme slice down\n // into that same top level. Running it earlier would leave a dark\n // override's font size unpinned.\n const authorSx = sanitizeAuthorSx(node?.sx)\n const composedSx = pinRampedTypographySx(\n resolvePaletteVarsSx(\n resolveSchemeSx(\n mergeSxProps(sx as any, propsSx as any, authorSx as any),\n activeScheme,\n ),\n theme?.palette,\n ),\n )\n /**\n * Author visibility — the eye on the hierarchy row.\n *\n * LAST, and deliberately so. It has to override the element's own\n * display, not replace it: an author who hides a Stack laid out with\n * `display: flex` gets that flex back the moment they show it again,\n * because the stored style was never touched. Writing `display: none`\n * into `node.sx` would have destroyed the value it overwrote, and there\n * would be nothing left to restore.\n *\n * The same rule on both surfaces. A hidden element is absent from the\n * published page and from the canvas — \"hidden\" that still renders in the\n * editor is a preview of a page nobody will ever see.\n */\n const mergedSx = node?.hidden\n ? mergeSxProps(composedSx as any, { display: 'none' } as any)\n : composedSx\n\n // Shared leaf attributes; self-closing components must receive NO\n // children at all (AGL-579) — a separate element expression keeps the\n // childless case genuinely childless instead of `[undefined, false]`.\n const leafProps = {\n ref,\n 'data-aglyn': `leaf:${node?.$id}`,\n // Before the spreads: the animation trigger/repeat attributes are ours,\n // but an element that genuinely declared one of these should win.\n ...animation?.attributes,\n ...resolvedProps,\n ...rest,\n className: mergedClassName,\n style: mergedStyle,\n sx: transformSx\n ? (transformSx(mergedSx, node?.$id) as typeof mergedSx)\n : mergedSx,\n }\n\n // Node identity (AGL-659): components get their node id through a\n // context rather than a prop, so a block can look up the server-seeded\n // slice of `pageData` that belongs to IT — two grids on one page have\n // different queries and must not share a seed. Nothing is added to any\n // component's props, so no unknown attribute reaches the DOM.\n // Positional children (AGL-1237): a component that splits its children\n // by index — MUI's Accordion is `[summary, ...rest]` — must receive one\n // React child per node child. The default single `<Branch>` element reads\n // as ONE child to `Children.toArray`, so the first slot swallowed the\n // whole subtree and every later slot got nothing.\n const positional = Boolean(\n (schema?.flags?.positionalChildren ?? 0) & FEATURE_FLAG.ENABLED,\n )\n const childNodes = positional ? (node?.children ?? []) : null\n\n const element = selfClosing ? (\n <Component {...leafProps} />\n ) : positional ? (\n <RendererComponents.Consumer>\n {({ StemComponent }) => (\n <Component {...leafProps}>\n {childNodes!.map((child: any, key: number) => (\n <StemComponent key={child?.$id ?? key} node={child} />\n ))}\n {textContent != null && (\n <AglynText>{textContent as any}</AglynText>\n )}\n </Component>\n )}\n </RendererComponents.Consumer>\n ) : (\n <Component {...leafProps}>\n {children}\n\n {textContent != null && (\n <AglynText>{textContent as any}</AglynText>\n )}\n </Component>\n )\n\n return (\n <NodeIdentityContext.Provider value={node?.$id ?? ''}>\n {element}\n </NodeIdentityContext.Provider>\n )\n }),\n)\nLeaf.displayName = 'Leaf'\nLeaf['aglyn'] = true\n\nexport default Leaf\n"],"names":["components","sanitizeAuthorSx","pinRampedTypographySx","NODE_HIDE_IF_PROP","NODE_HIDE_UNLESS_PROP","NODE_ANIMATION_DELAY_PROP","NODE_ANIMATION_DURATION_PROP","NODE_ANIMATION_EASE_PROP","NODE_ANIMATION_PROP","NODE_ANIMATION_REPEAT_PROP","NODE_ANIMATION_STAGGER_PROP","NODE_ANIMATION_STAGGER_STEP_PROP","NODE_ANIMATION_TRIGGER_PROP","resolveElementAnimation","EnabledPluginsContext","isSwitchedOffForRenderedSite","NodeIdentityContext","FEATURE_FLAG","AglynText","styled","useTheme","mergeSxProps","observer","forwardRef","useContext","isValidElementType","RendererComponents","LeafSxTransformContext","resolvePaletteVarsSx","resolveSchemeSx","DefaultComponent","Leaf","props","ref","node","schema","theme","children","sx","className","style","rest","resolvedProps","propsSx","propsClassName","propsStyle","_hideIf","_hideUnless","_animation","_animationTrigger","_animationDuration","_animationDelay","_animationRepeat","_animationEase","_animationStagger","_animationStaggerStep","animation","enabledPlugins","registeredSchema","getSchema","componentId","offForSite","pluginId","Factory","undefined","getFactory","Component","selfClosing","Boolean","flags","ENABLED","textContent","mergedClassName","filter","join","mergedStyle","transformSx","activeScheme","palette","mode","authorSx","composedSx","mergedSx","hidden","display","leafProps","$id","attributes","positional","positionalChildren","childNodes","element","Consumer","StemComponent","map","child","key","Provider","value","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn-node-renderer/src/lib/components/leaf.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Type-only, with every value this file reads named below (AGL-2486's rule,\n// applied to the render path's hottest file): a VALUE namespace import of the\n// core barrel is opaque to a bundler — it cannot know which exports are read,\n// so every module the barrel reaches is pinned into the published page's first\n// load.\nimport type * as Aglyn from '@aglyn/aglyn'\nimport { components } from '@aglyn/aglyn/aglyn'\nimport { sanitizeAuthorSx } from '@aglyn/aglyn/app-utils/author-css'\nimport { pinRampedTypographySx } from '@aglyn/aglyn/app-utils/responsive-typography-sx'\nimport {\n NODE_HIDE_IF_PROP,\n NODE_HIDE_UNLESS_PROP,\n} from '@aglyn/aglyn/app-utils/reusable-component-keys'\nimport {\n NODE_ANIMATION_DELAY_PROP,\n NODE_ANIMATION_DURATION_PROP,\n NODE_ANIMATION_EASE_PROP,\n NODE_ANIMATION_PROP,\n NODE_ANIMATION_REPEAT_PROP,\n NODE_ANIMATION_STAGGER_PROP,\n NODE_ANIMATION_STAGGER_STEP_PROP,\n NODE_ANIMATION_TRIGGER_PROP,\n resolveElementAnimation,\n} from '@aglyn/aglyn/app-utils/element-animation'\nimport {\n EnabledPluginsContext,\n isSwitchedOffForRenderedSite,\n} from '@aglyn/aglyn/app-utils/enabled-plugins-context'\nimport { NodeIdentityContext } from '@aglyn/aglyn/app-utils/node-identity'\nimport {\n NODE_COLOR_SCHEME_PROP,\n resolveElementColorScheme,\n} from '@aglyn/aglyn/app-utils/element-color-scheme'\nimport { FEATURE_FLAG } from '@aglyn/aglyn/foundation/constants/shared'\n// Deep import, NOT the barrel: `@aglyn/shared-ui-jsx`'s index re-exports the\n// Pages Router hooks (`next/router`), the inline SVG icon set and the whole\n// ~12,000-module MDI catalog, none of which a rendered node needs. This file\n// is on every published page, so the barrel's reach is that page's reach.\nimport { AglynText } from '@aglyn/shared-ui-jsx/components/aglyn-text'\nimport {\n styled,\n ThemeProvider,\n useSiteSchemeThemes,\n useTheme,\n} from '@aglyn/shared-ui-theme'\nimport { mergeSxProps } from '@aglyn/shared-ui-theme'\nimport { observer } from 'mobx-react-lite'\nimport { forwardRef, type HTMLAttributes, useContext } from 'react'\nimport { isValidElementType } from 'react-is'\nimport RendererComponents from '../contexts/renderer-components'\nimport { LeafSxTransformContext } from '../contexts/leaf-sx-transform'\nimport { resolvePaletteVarsSx, resolveSchemeSx } from '../utils/scheme-sx'\n\nconst DefaultComponent = styled('div')({})\n\nexport interface LeafProps extends HTMLAttributes<any> {\n children?: any\n node: Aglyn.NodeSchema\n sx?: JSX.SxProps\n}\n\nexport const Leaf = observer(\n forwardRef<any, LeafProps>((props, ref) => {\n const { children, node, sx, className, style, ...rest } = props\n\n // Pull sx/className/style out of the node's props so the spreads below\n // can never clobber the merged values composed explicitly afterwards\n // (AGL-569: `props.sx` used to overwrite the node-level sx entirely).\n //\n // The visibility directives (AGL-1314) come out here too. The compose\n // step consumes and strips them, so a rendered page never carries one —\n // but the component EDITOR renders definition nodes ungrafted, on\n // purpose (the author has to see and select the part a page will hide),\n // and there the raw `hideIf` would spread onto the element as an\n // unknown `hideif` DOM attribute.\n const {\n sx: propsSx,\n className: propsClassName,\n style: propsStyle,\n [NODE_HIDE_IF_PROP]: _hideIf,\n [NODE_HIDE_UNLESS_PROP]: _hideUnless,\n // Element animation (AGL-2486): the reserved animation props come\n // out here for the same reason the visibility directives above do —\n // they are directives to the RENDERER, and spreading them onto the\n // element would land `aglynanimation=\"slide-up\"` as an unknown DOM\n // attribute. Destructured rather than `delete`d after the fact so the\n // `none` case is stripped too (it resolves to no animation, but it is\n // still a prop an author saved) and so the props object keeps one\n // shape.\n [NODE_ANIMATION_PROP]: _animation,\n [NODE_ANIMATION_TRIGGER_PROP]: _animationTrigger,\n [NODE_ANIMATION_DURATION_PROP]: _animationDuration,\n [NODE_ANIMATION_DELAY_PROP]: _animationDelay,\n [NODE_ANIMATION_REPEAT_PROP]: _animationRepeat,\n [NODE_ANIMATION_EASE_PROP]: _animationEase,\n [NODE_ANIMATION_STAGGER_PROP]: _animationStagger,\n [NODE_ANIMATION_STAGGER_STEP_PROP]: _animationStaggerStep,\n // A pinned color scheme (AGL-3284) is a directive to the renderer, like\n // the two groups above: consumed below, never handed to the component.\n [NODE_COLOR_SCHEME_PROP]: _colorScheme,\n ...resolvedProps\n } = (node?.resolvedProps ?? node?.props ?? {}) as Record<string, any>\n\n // Resolves to a class, a `data-` attribute and two custom properties; the\n // keyframes themselves live in the tenant's stylesheet, so this costs no\n // JS on any surface. The besigner canvas never ships that stylesheet\n // (same posture as the AGL-562 hidden class), so an author sees the\n // element in its normal, selectable, un-animated state while editing.\n const animation = resolveElementAnimation({\n [NODE_ANIMATION_PROP]: _animation,\n [NODE_ANIMATION_TRIGGER_PROP]: _animationTrigger,\n [NODE_ANIMATION_DURATION_PROP]: _animationDuration,\n [NODE_ANIMATION_DELAY_PROP]: _animationDelay,\n [NODE_ANIMATION_REPEAT_PROP]: _animationRepeat,\n [NODE_ANIMATION_EASE_PROP]: _animationEase,\n [NODE_ANIMATION_STAGGER_PROP]: _animationStagger,\n [NODE_ANIMATION_STAGGER_STEP_PROP]: _animationStaggerStep,\n })\n // A component whose first-party plugin does not run on the rendered site\n // is drawn exactly as an unregistered one is (AGL-3033): the registry is\n // process-global and outlives the site that loaded the bundle, and the\n // site's own browser never loads it. Its schema goes with it, so the\n // void-element and positional flags cannot tell the server a different\n // story from the client either.\n const enabledPlugins = useContext(EnabledPluginsContext)\n const registeredSchema = components.getSchema(node?.componentId)\n const offForSite = isSwitchedOffForRenderedSite(\n registeredSchema?.pluginId,\n enabledPlugins,\n )\n const Factory = offForSite ? undefined : components.getFactory(node?.componentId)\n const Component = isValidElementType(Factory) ? Factory : DefaultComponent\n\n // Self-closing components (AGL-579): a component whose schema flags it\n // selfClosing renders a void DOM element (e.g. Image -> <img>), and React\n // throws during SSR when ANY children value reaches one — even the empty\n // `[undefined, false]` the JSX below always produces. Rendering the whole\n // page 500s off one image node (blog covers, AGL-579), so honor the flag\n // here: no JSX children, and strip a stray `children` prop too.\n const schema = offForSite ? undefined : registeredSchema\n const selfClosing = Boolean(\n (schema?.flags?.selfClosing ?? 0) & FEATURE_FLAG.ENABLED,\n )\n if (selfClosing) delete resolvedProps['children']\n\n const textContent = selfClosing ? null : resolvedProps?.['children']\n\n const mergedClassName =\n [propsClassName, node?.className, className, animation?.className]\n .filter(Boolean)\n .join(' ') || undefined\n // The animation's custom properties go in FIRST so an author who typed\n // `--aglyn-anim-duration` into the Custom CSS tab still wins.\n const mergedStyle =\n animation || propsStyle || style\n ? { ...animation?.style, ...propsStyle, ...style }\n : undefined\n\n // Canvas-only hook (AGL-581): the besigner provides a transform that\n // re-targets viewport media queries at the artboard device width.\n // Undefined everywhere else, keeping the tenant path unchanged.\n const transformSx = useContext(LeafSxTransformContext)\n // Scheme-scoped styles (AGL-588): sites swap a single-mode theme for\n // light/dark (tenant HostThemeProvider, canvas useAglynSiteTheme), so\n // '@scheme dark' sx slices resolve here against the ACTIVE theme's\n // palette mode — the one signal that is correct in both places.\n const theme = useTheme() as {\n palette?: { mode?: string } & Record<string, unknown>\n } | null\n const activeScheme = theme?.palette?.mode === 'dark' ? 'dark' : 'light'\n // \"Always light\" / \"Always dark\" (AGL-3284). When the pinned scheme is not\n // the active one, the element re-renders itself under the site's theme\n // for that scheme, so its OWN sx — not only its descendants' — resolves\n // palette tokens and `@scheme dark` slices for the pinned scheme. The\n // inner render then sees the pinned scheme as active and takes the plain\n // path; the mode check below is what guarantees that, because a site with\n // one theme for both schemes (a single `fallback`) hands back a theme\n // whose mode never changes, and re-wrapping it would never terminate.\n // No provider (an email render, a bare test) means nothing to force.\n // Every hook above runs on both paths, so the early return keeps the\n // hook order stable when an author flips the setting.\n const pinnedScheme = resolveElementColorScheme(_colorScheme)\n const schemeThemes = useSiteSchemeThemes()\n const forcedTheme =\n pinnedScheme && pinnedScheme !== activeScheme && schemeThemes\n ? schemeThemes(pinnedScheme)\n : undefined\n if (forcedTheme && forcedTheme.palette?.mode === pinnedScheme) {\n return (\n <ThemeProvider theme={forcedTheme}>\n <Leaf {...props} ref={ref} />\n </ThemeProvider>\n )\n }\n // MUI array composition: later entries win on key conflicts, so the\n // node-level sx (Styles panel output) overrides props.sx.\n //\n // Palette token references (AGL-1331): the Background Fill field\n // persists a token-bound gradient stop as\n // `var(--mui-palette-primary-main, #00B0FF)`, because `backgroundImage`\n // is NOT one of the sx keys MUI resolves against the palette. They are\n // substituted here, against the site theme, so the canvas cannot pick\n // up the console's `--mui-palette-*` and the tenant (whose theme has no\n // CSS variables at all) still tracks palette changes. Values carrying\n // no reference come back by identity.\n // Author CSS (AGL-1725): `node.sx` is the Styles panel's output, and it\n // is free text — `backgroundImage` is a first-class field and the Custom\n // CSS tab is free-solo, so any property and any value can be typed. On a\n // published site that lands in the visitor's document as a real `url()`,\n // which no input validator and no lint rule can see. Scrubbed HERE, at\n // the last point before the merge, so it also catches values already\n // stored; `sx` and `props.sx` are OUR components' own styles and are\n // deliberately left alone. The scrub is scheme-only and returns its\n // input by identity when nothing is refused, so the overwhelmingly\n // common case (no `url()` at all) costs one walk and no new object.\n // Responsive type ramp: LAST of the three sx passes, and it has to be —\n // it moves a scalar `fontSize` into the `xs` slice so the author's\n // explicit size sorts after the variant's `responsiveFontSizes` at-rules,\n // and the scheme pass above is what collapses a dark-scheme slice down\n // into that same top level. Running it earlier would leave a dark\n // override's font size unpinned.\n //\n // A pinned element paints its scheme's page background and text color\n // (AGL-3284), UNDER every other style so an author's own background wins.\n // Without it an \"Always dark\" band with no background of its own is\n // light text on the light page behind it, and text that sets no color\n // inherits the page's dark body color. `color-scheme` makes the browser's\n // own controls and scrollbars inside the band match. Only a pinned\n // element carries this, so an unpinned one renders exactly as before —\n // and so does a pinned one on a surface with no site themes to pin to.\n const authorSx = sanitizeAuthorSx(node?.sx)\n const composedSx = pinRampedTypographySx(\n resolvePaletteVarsSx(\n resolveSchemeSx(\n pinnedScheme && schemeThemes\n ? mergeSxProps(\n {\n colorScheme: pinnedScheme,\n color: 'text.primary',\n bgcolor: 'background.default',\n } as any,\n sx as any,\n propsSx as any,\n authorSx as any,\n )\n : mergeSxProps(sx as any, propsSx as any, authorSx as any),\n activeScheme,\n ),\n theme?.palette,\n ),\n )\n /**\n * Author visibility — the eye on the hierarchy row.\n *\n * LAST, and deliberately so. It has to override the element's own\n * display, not replace it: an author who hides a Stack laid out with\n * `display: flex` gets that flex back the moment they show it again,\n * because the stored style was never touched. Writing `display: none`\n * into `node.sx` would have destroyed the value it overwrote, and there\n * would be nothing left to restore.\n *\n * The same rule on both surfaces. A hidden element is absent from the\n * published page and from the canvas — \"hidden\" that still renders in the\n * editor is a preview of a page nobody will ever see.\n */\n const mergedSx = node?.hidden\n ? mergeSxProps(composedSx as any, { display: 'none' } as any)\n : composedSx\n\n // Shared leaf attributes; self-closing components must receive NO\n // children at all (AGL-579) — a separate element expression keeps the\n // childless case genuinely childless instead of `[undefined, false]`.\n const leafProps = {\n ref,\n 'data-aglyn': `leaf:${node?.$id}`,\n // Before the spreads: the animation trigger/repeat attributes are ours,\n // but an element that genuinely declared one of these should win.\n ...animation?.attributes,\n ...resolvedProps,\n ...rest,\n className: mergedClassName,\n style: mergedStyle,\n sx: transformSx\n ? (transformSx(mergedSx, node?.$id) as typeof mergedSx)\n : mergedSx,\n }\n\n // Node identity (AGL-659): components get their node id through a\n // context rather than a prop, so a block can look up the server-seeded\n // slice of `pageData` that belongs to IT — two grids on one page have\n // different queries and must not share a seed. Nothing is added to any\n // component's props, so no unknown attribute reaches the DOM.\n // Positional children (AGL-1237): a component that splits its children\n // by index — MUI's Accordion is `[summary, ...rest]` — must receive one\n // React child per node child. The default single `<Branch>` element reads\n // as ONE child to `Children.toArray`, so the first slot swallowed the\n // whole subtree and every later slot got nothing.\n const positional = Boolean(\n (schema?.flags?.positionalChildren ?? 0) & FEATURE_FLAG.ENABLED,\n )\n const childNodes = positional ? (node?.children ?? []) : null\n\n const element = selfClosing ? (\n <Component {...leafProps} />\n ) : positional ? (\n <RendererComponents.Consumer>\n {({ StemComponent }) => (\n <Component {...leafProps}>\n {childNodes!.map((child: any, key: number) => (\n <StemComponent key={child?.$id ?? key} node={child} />\n ))}\n {textContent != null && (\n <AglynText>{textContent as any}</AglynText>\n )}\n </Component>\n )}\n </RendererComponents.Consumer>\n ) : (\n <Component {...leafProps}>\n {children}\n\n {textContent != null && (\n <AglynText>{textContent as any}</AglynText>\n )}\n </Component>\n )\n\n return (\n <NodeIdentityContext.Provider value={node?.$id ?? ''}>\n {element}\n </NodeIdentityContext.Provider>\n )\n }),\n)\nLeaf.displayName = 'Leaf'\nLeaf['aglyn'] = true\n\nexport default Leaf\n"],"names":["components","sanitizeAuthorSx","pinRampedTypographySx","NODE_HIDE_IF_PROP","NODE_HIDE_UNLESS_PROP","NODE_ANIMATION_DELAY_PROP","NODE_ANIMATION_DURATION_PROP","NODE_ANIMATION_EASE_PROP","NODE_ANIMATION_PROP","NODE_ANIMATION_REPEAT_PROP","NODE_ANIMATION_STAGGER_PROP","NODE_ANIMATION_STAGGER_STEP_PROP","NODE_ANIMATION_TRIGGER_PROP","resolveElementAnimation","EnabledPluginsContext","isSwitchedOffForRenderedSite","NodeIdentityContext","NODE_COLOR_SCHEME_PROP","resolveElementColorScheme","FEATURE_FLAG","AglynText","styled","ThemeProvider","useSiteSchemeThemes","useTheme","mergeSxProps","observer","forwardRef","useContext","isValidElementType","RendererComponents","LeafSxTransformContext","resolvePaletteVarsSx","resolveSchemeSx","DefaultComponent","Leaf","props","ref","node","schema","theme","forcedTheme","children","sx","className","style","rest","resolvedProps","propsSx","propsClassName","propsStyle","_hideIf","_hideUnless","_animation","_animationTrigger","_animationDuration","_animationDelay","_animationRepeat","_animationEase","_animationStagger","_animationStaggerStep","_colorScheme","animation","enabledPlugins","registeredSchema","getSchema","componentId","offForSite","pluginId","Factory","undefined","getFactory","Component","selfClosing","Boolean","flags","ENABLED","textContent","mergedClassName","filter","join","mergedStyle","transformSx","activeScheme","palette","mode","pinnedScheme","schemeThemes","authorSx","composedSx","colorScheme","color","bgcolor","mergedSx","hidden","display","leafProps","$id","attributes","positional","positionalChildren","childNodes","element","Consumer","StemComponent","map","child","key","Provider","value","displayName"],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import type { HostTheme, HostThemeScheme } from '@aglyn/shared-data-types';
|
|
18
|
+
import { type SiteSchemeThemes, type Theme } from '@aglyn/shared-ui-theme';
|
|
18
19
|
export type UseAglynSiteThemeOptions = {
|
|
19
20
|
container?: Element | Node;
|
|
20
21
|
/** Persisted host theme customization; omitted → default light theme (legacy behavior). */
|
|
@@ -42,6 +43,24 @@ export type UseAglynSiteThemeOptions = {
|
|
|
42
43
|
* that renders a site outside React's hooks — the AI plugin's device-width
|
|
43
44
|
* audit of its golden pages (AGL-3020) — builds the same theme here.
|
|
44
45
|
*/
|
|
45
|
-
export declare function createAglynSiteTheme(options?: UseAglynSiteThemeOptions):
|
|
46
|
-
export declare function useAglynSiteTheme(options?: UseAglynSiteThemeOptions):
|
|
46
|
+
export declare function createAglynSiteTheme(options?: UseAglynSiteThemeOptions): Theme;
|
|
47
|
+
export declare function useAglynSiteTheme(options?: UseAglynSiteThemeOptions): Theme;
|
|
48
|
+
/**
|
|
49
|
+
* The site's theme for EITHER scheme, for `SiteSchemeThemesContext`
|
|
50
|
+
* (AGL-3284) — what an "Always light" / "Always dark" element renders under on
|
|
51
|
+
* the canvas and in Preview.
|
|
52
|
+
*
|
|
53
|
+
* Built by {@link createAglynSiteTheme} from the same inputs
|
|
54
|
+
* {@link useAglynSiteTheme} takes, so a pinned band on the canvas wears
|
|
55
|
+
* exactly what the published page's `HostThemeProvider` would give it.
|
|
56
|
+
* `active` is the theme the surface is already rendering; it is answered for
|
|
57
|
+
* its own scheme rather than rebuilt, so a surface that has pinned or patched
|
|
58
|
+
* its theme (the canvas's device width) keeps that for the matching scheme.
|
|
59
|
+
* `finish` applies the same patch to the other scheme's theme; memoize it, as
|
|
60
|
+
* the getter is rebuilt when it changes.
|
|
61
|
+
*/
|
|
62
|
+
export declare function useAglynSiteSchemeThemes(options: Omit<UseAglynSiteThemeOptions, 'scheme'> & {
|
|
63
|
+
active: Theme;
|
|
64
|
+
finish?: (theme: Theme) => Theme;
|
|
65
|
+
}): SiteSchemeThemes;
|
|
47
66
|
export default useAglynSiteTheme;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
17
|
-
import { createResponsiveTheme, hostThemeToThemeOptions, mergeThemeOptions, siteBaseOptions, useHostSiteKey } from "@aglyn/shared-ui-theme";
|
|
17
|
+
import { createResponsiveTheme, createSiteSchemeThemes, hostThemeToThemeOptions, mergeThemeOptions, siteBaseOptions, useHostSiteKey } from "@aglyn/shared-ui-theme";
|
|
18
18
|
import { useMemo } from "react";
|
|
19
19
|
/**
|
|
20
20
|
* The theme a site renders with on the canvas and in Preview: the host's
|
|
@@ -91,6 +91,42 @@ export function useAglynSiteTheme(options = {}) {
|
|
|
91
91
|
host
|
|
92
92
|
]);
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* The site's theme for EITHER scheme, for `SiteSchemeThemesContext`
|
|
96
|
+
* (AGL-3284) — what an "Always light" / "Always dark" element renders under on
|
|
97
|
+
* the canvas and in Preview.
|
|
98
|
+
*
|
|
99
|
+
* Built by {@link createAglynSiteTheme} from the same inputs
|
|
100
|
+
* {@link useAglynSiteTheme} takes, so a pinned band on the canvas wears
|
|
101
|
+
* exactly what the published page's `HostThemeProvider` would give it.
|
|
102
|
+
* `active` is the theme the surface is already rendering; it is answered for
|
|
103
|
+
* its own scheme rather than rebuilt, so a surface that has pinned or patched
|
|
104
|
+
* its theme (the canvas's device width) keeps that for the matching scheme.
|
|
105
|
+
* `finish` applies the same patch to the other scheme's theme; memoize it, as
|
|
106
|
+
* the getter is rebuilt when it changes.
|
|
107
|
+
*/ export function useAglynSiteSchemeThemes(options) {
|
|
108
|
+
var _options_host;
|
|
109
|
+
const { container, theme: hostTheme, active, finish } = options;
|
|
110
|
+
const contextHost = useHostSiteKey();
|
|
111
|
+
const host = (_options_host = options.host) != null ? _options_host : contextHost;
|
|
112
|
+
return useMemo(()=>createSiteSchemeThemes((scheme)=>{
|
|
113
|
+
var _active_palette;
|
|
114
|
+
if ((((_active_palette = active.palette) == null ? void 0 : _active_palette.mode) === 'dark' ? 'dark' : 'light') === scheme) return active;
|
|
115
|
+
const built = createAglynSiteTheme({
|
|
116
|
+
container,
|
|
117
|
+
theme: hostTheme,
|
|
118
|
+
scheme,
|
|
119
|
+
host
|
|
120
|
+
});
|
|
121
|
+
return finish ? finish(built) : built;
|
|
122
|
+
}), [
|
|
123
|
+
active,
|
|
124
|
+
finish,
|
|
125
|
+
container,
|
|
126
|
+
hostTheme,
|
|
127
|
+
host
|
|
128
|
+
]);
|
|
129
|
+
}
|
|
94
130
|
export default useAglynSiteTheme;
|
|
95
131
|
|
|
96
132
|
//# sourceMappingURL=use-aglyn-site-theme.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn-node-renderer/src/lib/hooks/use-aglyn-site-theme.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { HostTheme, HostThemeScheme } from '@aglyn/shared-data-types'\nimport {\n createResponsiveTheme,\n hostThemeToThemeOptions,\n mergeThemeOptions,\n siteBaseOptions,\n useHostSiteKey,\n} from '@aglyn/shared-ui-theme'\nimport { useMemo } from 'react'\n\nexport type UseAglynSiteThemeOptions = {\n // Node covers ShadowRoot containers, which MUI accepts at runtime but\n // types as Element only.\n container?: Element | Node\n /** Persisted host theme customization; omitted → default light theme (legacy behavior). */\n theme?: HostTheme\n scheme?: HostThemeScheme\n /**\n * Which site this is — its attached domain, or its subdomain (AGL-3068).\n *\n * It decides the BASE the site's overrides are layered onto, which is the\n * one thing the editor cannot derive from the theme document: the operator's\n * own hosts keep the platform brand, every customer site resolves the\n * neutral tenant default, and the published page has already made that\n * choice from its own address. Unnamed resolves what a customer site\n * resolves.\n *\n * `useAglynSiteTheme` falls back to `HostSiteKeyContext`, so a surface\n * inside the console's host routes needs to pass nothing.\n */\n host?: string\n}\n\n/**\n * The theme a site renders with on the canvas and in Preview: the host's\n * overrides layered onto the base that site publishes on, with MUI's portals\n * pointed at the container. {@link useAglynSiteTheme} memoizes it; anything\n * that renders a site outside React's hooks — the AI plugin's device-width\n * audit of its golden pages (AGL-3020) — builds the same theme here.\n */\nexport function createAglynSiteTheme(options: UseAglynSiteThemeOptions = {}) {\n const container = options.container as Element | undefined\n const hostTheme = options.theme\n const scheme = options.scheme ?? 'light'\n // Layer the host's overrides onto the base the PUBLISHED PAGE uses, chosen\n // from the same site key the tenant chooses from (AGL-1180/AGL-1205,\n // AGL-3068). `hostThemeToThemeOptions` emits only what the host explicitly\n // set, so building from it alone leaves every untouched slot on MUI's stock\n // palette — and a site that keeps its theme all-`Default` has nothing else.\n // Which base is not a constant: the operator's own hosts wear the platform\n // brand and a customer site wears the neutral tenant default, so a canvas\n // that always took the brand painted Aglyn cyan over a site that publishes\n // in blue, including its contrast.\n const themeOptions = mergeThemeOptions(\n siteBaseOptions(options.host, scheme),\n hostThemeToThemeOptions(hostTheme, scheme),\n )\n // createResponsiveTheme, not plain createTheme (AGL-593): the tenant\n // builds host themes through it (HostThemeProvider), which bakes\n // responsive font sizes into the typography variants — the canvas\n // must carry the same media-keyed typography or device preview has\n // nothing to re-resolve and canvas/tenant text sizes disagree.\n return createResponsiveTheme({\n themeOptions: {\n ...themeOptions,\n components: {\n ...themeOptions.components,\n // Spread the existing entry per component: now that the brand base\n // is merged in, replacing these wholesale would drop any\n // `styleOverrides` it ships for them. Only `defaultProps.container`\n // is ours to set — it points MUI's portals at the canvas container.\n MuiPopover: {\n ...themeOptions.components?.MuiPopover,\n defaultProps: {\n ...themeOptions.components?.MuiPopover?.defaultProps,\n container: container,\n },\n },\n MuiPopper: {\n ...themeOptions.components?.MuiPopper,\n defaultProps: {\n ...themeOptions.components?.MuiPopper?.defaultProps,\n container: container,\n },\n },\n MuiModal: {\n ...themeOptions.components?.MuiModal,\n defaultProps: {\n ...themeOptions.components?.MuiModal?.defaultProps,\n container: container,\n },\n },\n },\n },\n })\n}\n\nexport function useAglynSiteTheme(options: UseAglynSiteThemeOptions = {}) {\n const container = options.container\n const hostTheme = options.theme\n const scheme = options.scheme ?? 'light'\n // The surface names its site, or the route it is on does. Every besigner\n // panel and preview reads the same context, so the base is decided once per\n // editor rather than per component.\n const contextHost = useHostSiteKey()\n const host = options.host ?? contextHost\n\n return useMemo(\n () => createAglynSiteTheme({ container, theme: hostTheme, scheme, host }),\n [container, hostTheme, scheme, host],\n )\n}\nexport default useAglynSiteTheme\n"],"names":["createResponsiveTheme","hostThemeToThemeOptions","mergeThemeOptions","siteBaseOptions","useHostSiteKey","useMemo","createAglynSiteTheme","options","themeOptions","container","hostTheme","theme","scheme","host","components","MuiPopover","defaultProps","MuiPopper","MuiModal","useAglynSiteTheme","contextHost"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SACEA,qBAAqB,EACrBC,uBAAuB,EACvBC,iBAAiB,
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn-node-renderer/src/lib/hooks/use-aglyn-site-theme.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { HostTheme, HostThemeScheme } from '@aglyn/shared-data-types'\nimport {\n createResponsiveTheme,\n createSiteSchemeThemes,\n hostThemeToThemeOptions,\n mergeThemeOptions,\n type SiteSchemeThemes,\n siteBaseOptions,\n type Theme,\n useHostSiteKey,\n} from '@aglyn/shared-ui-theme'\nimport { useMemo } from 'react'\n\nexport type UseAglynSiteThemeOptions = {\n // Node covers ShadowRoot containers, which MUI accepts at runtime but\n // types as Element only.\n container?: Element | Node\n /** Persisted host theme customization; omitted → default light theme (legacy behavior). */\n theme?: HostTheme\n scheme?: HostThemeScheme\n /**\n * Which site this is — its attached domain, or its subdomain (AGL-3068).\n *\n * It decides the BASE the site's overrides are layered onto, which is the\n * one thing the editor cannot derive from the theme document: the operator's\n * own hosts keep the platform brand, every customer site resolves the\n * neutral tenant default, and the published page has already made that\n * choice from its own address. Unnamed resolves what a customer site\n * resolves.\n *\n * `useAglynSiteTheme` falls back to `HostSiteKeyContext`, so a surface\n * inside the console's host routes needs to pass nothing.\n */\n host?: string\n}\n\n/**\n * The theme a site renders with on the canvas and in Preview: the host's\n * overrides layered onto the base that site publishes on, with MUI's portals\n * pointed at the container. {@link useAglynSiteTheme} memoizes it; anything\n * that renders a site outside React's hooks — the AI plugin's device-width\n * audit of its golden pages (AGL-3020) — builds the same theme here.\n */\nexport function createAglynSiteTheme(options: UseAglynSiteThemeOptions = {}) {\n const container = options.container as Element | undefined\n const hostTheme = options.theme\n const scheme = options.scheme ?? 'light'\n // Layer the host's overrides onto the base the PUBLISHED PAGE uses, chosen\n // from the same site key the tenant chooses from (AGL-1180/AGL-1205,\n // AGL-3068). `hostThemeToThemeOptions` emits only what the host explicitly\n // set, so building from it alone leaves every untouched slot on MUI's stock\n // palette — and a site that keeps its theme all-`Default` has nothing else.\n // Which base is not a constant: the operator's own hosts wear the platform\n // brand and a customer site wears the neutral tenant default, so a canvas\n // that always took the brand painted Aglyn cyan over a site that publishes\n // in blue, including its contrast.\n const themeOptions = mergeThemeOptions(\n siteBaseOptions(options.host, scheme),\n hostThemeToThemeOptions(hostTheme, scheme),\n )\n // createResponsiveTheme, not plain createTheme (AGL-593): the tenant\n // builds host themes through it (HostThemeProvider), which bakes\n // responsive font sizes into the typography variants — the canvas\n // must carry the same media-keyed typography or device preview has\n // nothing to re-resolve and canvas/tenant text sizes disagree.\n return createResponsiveTheme({\n themeOptions: {\n ...themeOptions,\n components: {\n ...themeOptions.components,\n // Spread the existing entry per component: now that the brand base\n // is merged in, replacing these wholesale would drop any\n // `styleOverrides` it ships for them. Only `defaultProps.container`\n // is ours to set — it points MUI's portals at the canvas container.\n MuiPopover: {\n ...themeOptions.components?.MuiPopover,\n defaultProps: {\n ...themeOptions.components?.MuiPopover?.defaultProps,\n container: container,\n },\n },\n MuiPopper: {\n ...themeOptions.components?.MuiPopper,\n defaultProps: {\n ...themeOptions.components?.MuiPopper?.defaultProps,\n container: container,\n },\n },\n MuiModal: {\n ...themeOptions.components?.MuiModal,\n defaultProps: {\n ...themeOptions.components?.MuiModal?.defaultProps,\n container: container,\n },\n },\n },\n },\n })\n}\n\nexport function useAglynSiteTheme(options: UseAglynSiteThemeOptions = {}) {\n const container = options.container\n const hostTheme = options.theme\n const scheme = options.scheme ?? 'light'\n // The surface names its site, or the route it is on does. Every besigner\n // panel and preview reads the same context, so the base is decided once per\n // editor rather than per component.\n const contextHost = useHostSiteKey()\n const host = options.host ?? contextHost\n\n return useMemo(\n () => createAglynSiteTheme({ container, theme: hostTheme, scheme, host }),\n [container, hostTheme, scheme, host],\n )\n}\n/**\n * The site's theme for EITHER scheme, for `SiteSchemeThemesContext`\n * (AGL-3284) — what an \"Always light\" / \"Always dark\" element renders under on\n * the canvas and in Preview.\n *\n * Built by {@link createAglynSiteTheme} from the same inputs\n * {@link useAglynSiteTheme} takes, so a pinned band on the canvas wears\n * exactly what the published page's `HostThemeProvider` would give it.\n * `active` is the theme the surface is already rendering; it is answered for\n * its own scheme rather than rebuilt, so a surface that has pinned or patched\n * its theme (the canvas's device width) keeps that for the matching scheme.\n * `finish` applies the same patch to the other scheme's theme; memoize it, as\n * the getter is rebuilt when it changes.\n */\nexport function useAglynSiteSchemeThemes(\n options: Omit<UseAglynSiteThemeOptions, 'scheme'> & {\n active: Theme\n finish?: (theme: Theme) => Theme\n },\n): SiteSchemeThemes {\n const { container, theme: hostTheme, active, finish } = options\n const contextHost = useHostSiteKey()\n const host = options.host ?? contextHost\n return useMemo(\n () =>\n createSiteSchemeThemes((scheme) => {\n if ((active.palette?.mode === 'dark' ? 'dark' : 'light') === scheme)\n return active\n const built = createAglynSiteTheme({\n container,\n theme: hostTheme,\n scheme,\n host,\n })\n return finish ? finish(built) : built\n }),\n [active, finish, container, hostTheme, host],\n )\n}\n\nexport default useAglynSiteTheme\n"],"names":["createResponsiveTheme","createSiteSchemeThemes","hostThemeToThemeOptions","mergeThemeOptions","siteBaseOptions","useHostSiteKey","useMemo","createAglynSiteTheme","options","themeOptions","container","hostTheme","theme","scheme","host","components","MuiPopover","defaultProps","MuiPopper","MuiModal","useAglynSiteTheme","contextHost","useAglynSiteSchemeThemes","active","finish","palette","mode","built"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SACEA,qBAAqB,EACrBC,sBAAsB,EACtBC,uBAAuB,EACvBC,iBAAiB,EAEjBC,eAAe,EAEfC,cAAc,QACT,yBAAwB;AAC/B,SAASC,OAAO,QAAQ,QAAO;AAyB/B;;;;;;CAMC,GACD,OAAO,SAASC,qBAAqBC,UAAoC,CAAC,CAAC;QAG1DA;QA6BJC,0BAEEA,qCAAAA,2BAKFA,2BAEEA,oCAAAA,2BAKFA,2BAEEA,mCAAAA;IA/Cb,MAAMC,YAAYF,QAAQE,SAAS;IACnC,MAAMC,YAAYH,QAAQI,KAAK;IAC/B,MAAMC,UAASL,kBAAAA,QAAQK,MAAM,YAAdL,kBAAkB;IACjC,2EAA2E;IAC3E,qEAAqE;IACrE,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,0EAA0E;IAC1E,2EAA2E;IAC3E,mCAAmC;IACnC,MAAMC,eAAeN,kBACnBC,gBAAgBI,QAAQM,IAAI,EAAED,SAC9BX,wBAAwBS,WAAWE;IAErC,qEAAqE;IACrE,iEAAiE;IACjE,kEAAkE;IAClE,mEAAmE;IACnE,+DAA+D;IAC/D,OAAOb,sBAAsB;QAC3BS,cAAc,aACTA;YACHM,YAAY,aACPN,aAAaM,UAAU;gBAC1B,mEAAmE;gBACnE,yDAAyD;gBACzD,oEAAoE;gBACpE,oEAAoE;gBACpEC,YAAY,cACPP,2BAAAA,aAAaM,UAAU,qBAAvBN,yBAAyBO,UAAU;oBACtCC,cAAc,cACTR,4BAAAA,aAAaM,UAAU,sBAAvBN,sCAAAA,0BAAyBO,UAAU,qBAAnCP,oCAAqCQ,YAAY;wBACpDP,WAAWA;;;gBAGfQ,WAAW,cACNT,4BAAAA,aAAaM,UAAU,qBAAvBN,0BAAyBS,SAAS;oBACrCD,cAAc,cACTR,4BAAAA,aAAaM,UAAU,sBAAvBN,qCAAAA,0BAAyBS,SAAS,qBAAlCT,mCAAoCQ,YAAY;wBACnDP,WAAWA;;;gBAGfS,UAAU,cACLV,4BAAAA,aAAaM,UAAU,qBAAvBN,0BAAyBU,QAAQ;oBACpCF,cAAc,cACTR,4BAAAA,aAAaM,UAAU,sBAAvBN,oCAAAA,0BAAyBU,QAAQ,qBAAjCV,kCAAmCQ,YAAY;wBAClDP,WAAWA;;;;;IAKrB;AACF;AAEA,OAAO,SAASU,kBAAkBZ,UAAoC,CAAC,CAAC;QAGvDA,iBAKFA;IAPb,MAAME,YAAYF,QAAQE,SAAS;IACnC,MAAMC,YAAYH,QAAQI,KAAK;IAC/B,MAAMC,UAASL,kBAAAA,QAAQK,MAAM,YAAdL,kBAAkB;IACjC,yEAAyE;IACzE,4EAA4E;IAC5E,oCAAoC;IACpC,MAAMa,cAAchB;IACpB,MAAMS,QAAON,gBAAAA,QAAQM,IAAI,YAAZN,gBAAgBa;IAE7B,OAAOf,QACL,IAAMC,qBAAqB;YAAEG;YAAWE,OAAOD;YAAWE;YAAQC;QAAK,IACvE;QAACJ;QAAWC;QAAWE;QAAQC;KAAK;AAExC;AACA;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASQ,yBACdd,OAGC;QAIYA;IAFb,MAAM,EAAEE,SAAS,EAAEE,OAAOD,SAAS,EAAEY,MAAM,EAAEC,MAAM,EAAE,GAAGhB;IACxD,MAAMa,cAAchB;IACpB,MAAMS,QAAON,gBAAAA,QAAQM,IAAI,YAAZN,gBAAgBa;IAC7B,OAAOf,QACL,IACEL,uBAAuB,CAACY;gBACjBU;YAAL,IAAI,AAACA,CAAAA,EAAAA,kBAAAA,OAAOE,OAAO,qBAAdF,gBAAgBG,IAAI,MAAK,SAAS,SAAS,OAAM,MAAOb,QAC3D,OAAOU;YACT,MAAMI,QAAQpB,qBAAqB;gBACjCG;gBACAE,OAAOD;gBACPE;gBACAC;YACF;YACA,OAAOU,SAASA,OAAOG,SAASA;QAClC,IACF;QAACJ;QAAQC;QAAQd;QAAWC;QAAWG;KAAK;AAEhD;AAEA,eAAeM,kBAAiB"}
|