@aglyn/plugins-mui 1.0.0-beta.143
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 +201 -0
- package/README.md +22 -0
- package/package.json +47 -0
- package/src/index.d.ts +21 -0
- package/src/index.js +22 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/accordion.d.ts +96 -0
- package/src/lib/components/accordion.js +392 -0
- package/src/lib/components/accordion.js.map +1 -0
- package/src/lib/components/app-bar.d.ts +32 -0
- package/src/lib/components/app-bar.js +86 -0
- package/src/lib/components/app-bar.js.map +1 -0
- package/src/lib/components/blocks.d.ts +46 -0
- package/src/lib/components/blocks.js +1007 -0
- package/src/lib/components/blocks.js.map +1 -0
- package/src/lib/components/box.d.ts +47 -0
- package/src/lib/components/box.js +125 -0
- package/src/lib/components/box.js.map +1 -0
- package/src/lib/components/breadcrumbs.d.ts +44 -0
- package/src/lib/components/breadcrumbs.js +172 -0
- package/src/lib/components/breadcrumbs.js.map +1 -0
- package/src/lib/components/button.d.ts +89 -0
- package/src/lib/components/button.js +272 -0
- package/src/lib/components/button.js.map +1 -0
- package/src/lib/components/card.d.ts +61 -0
- package/src/lib/components/card.js +336 -0
- package/src/lib/components/card.js.map +1 -0
- package/src/lib/components/collection.d.ts +514 -0
- package/src/lib/components/collection.js +2999 -0
- package/src/lib/components/collection.js.map +1 -0
- package/src/lib/components/container.d.ts +42 -0
- package/src/lib/components/container.js +169 -0
- package/src/lib/components/container.js.map +1 -0
- package/src/lib/components/custom-html.d.ts +78 -0
- package/src/lib/components/custom-html.js +219 -0
- package/src/lib/components/custom-html.js.map +1 -0
- package/src/lib/components/data-table.d.ts +57 -0
- package/src/lib/components/data-table.js +216 -0
- package/src/lib/components/data-table.js.map +1 -0
- package/src/lib/components/document-root.d.ts +77 -0
- package/src/lib/components/document-root.js +118 -0
- package/src/lib/components/document-root.js.map +1 -0
- package/src/lib/components/drawer.d.ts +93 -0
- package/src/lib/components/drawer.js +566 -0
- package/src/lib/components/drawer.js.map +1 -0
- package/src/lib/components/function-controls.d.ts +66 -0
- package/src/lib/components/function-controls.js +207 -0
- package/src/lib/components/function-controls.js.map +1 -0
- package/src/lib/components/function-scope.d.ts +110 -0
- package/src/lib/components/function-scope.js +478 -0
- package/src/lib/components/function-scope.js.map +1 -0
- package/src/lib/components/function-widget.d.ts +75 -0
- package/src/lib/components/function-widget.js +307 -0
- package/src/lib/components/function-widget.js.map +1 -0
- package/src/lib/components/grid.d.ts +91 -0
- package/src/lib/components/grid.js +322 -0
- package/src/lib/components/grid.js.map +1 -0
- package/src/lib/components/icon.d.ts +54 -0
- package/src/lib/components/icon.js +163 -0
- package/src/lib/components/icon.js.map +1 -0
- package/src/lib/components/image-list.d.ts +58 -0
- package/src/lib/components/image-list.js +336 -0
- package/src/lib/components/image-list.js.map +1 -0
- package/src/lib/components/image.d.ts +154 -0
- package/src/lib/components/image.js +451 -0
- package/src/lib/components/image.js.map +1 -0
- package/src/lib/components/inline-text.d.ts +74 -0
- package/src/lib/components/inline-text.js +407 -0
- package/src/lib/components/inline-text.js.map +1 -0
- package/src/lib/components/language-switcher.d.ts +35 -0
- package/src/lib/components/language-switcher.js +179 -0
- package/src/lib/components/language-switcher.js.map +1 -0
- package/src/lib/components/layout-slot.d.ts +68 -0
- package/src/lib/components/layout-slot.js +192 -0
- package/src/lib/components/layout-slot.js.map +1 -0
- package/src/lib/components/link-box-accessible-name.d.ts +79 -0
- package/src/lib/components/link-box-accessible-name.js +158 -0
- package/src/lib/components/link-box-accessible-name.js.map +1 -0
- package/src/lib/components/link-box.d.ts +66 -0
- package/src/lib/components/link-box.js +212 -0
- package/src/lib/components/link-box.js.map +1 -0
- package/src/lib/components/list-item-text.d.ts +22 -0
- package/src/lib/components/list-item-text.js +86 -0
- package/src/lib/components/list-item-text.js.map +1 -0
- package/src/lib/components/list-item.d.ts +32 -0
- package/src/lib/components/list-item.js +127 -0
- package/src/lib/components/list-item.js.map +1 -0
- package/src/lib/components/list.d.ts +34 -0
- package/src/lib/components/list.js +108 -0
- package/src/lib/components/list.js.map +1 -0
- package/src/lib/components/markdown.d.ts +129 -0
- package/src/lib/components/markdown.js +853 -0
- package/src/lib/components/markdown.js.map +1 -0
- package/src/lib/components/nav-menu.d.ts +68 -0
- package/src/lib/components/nav-menu.js +683 -0
- package/src/lib/components/nav-menu.js.map +1 -0
- package/src/lib/components/pagination.d.ts +59 -0
- package/src/lib/components/pagination.js +243 -0
- package/src/lib/components/pagination.js.map +1 -0
- package/src/lib/components/paper.d.ts +47 -0
- package/src/lib/components/paper.js +202 -0
- package/src/lib/components/paper.js.map +1 -0
- package/src/lib/components/plugin-frame.d.ts +64 -0
- package/src/lib/components/plugin-frame.js +335 -0
- package/src/lib/components/plugin-frame.js.map +1 -0
- package/src/lib/components/plugin.d.ts +95 -0
- package/src/lib/components/plugin.js +304 -0
- package/src/lib/components/plugin.js.map +1 -0
- package/src/lib/components/product.d.ts +40 -0
- package/src/lib/components/product.js +287 -0
- package/src/lib/components/product.js.map +1 -0
- package/src/lib/components/reusable-instance.d.ts +57 -0
- package/src/lib/components/reusable-instance.js +126 -0
- package/src/lib/components/reusable-instance.js.map +1 -0
- package/src/lib/components/screen-link.d.ts +85 -0
- package/src/lib/components/screen-link.js +324 -0
- package/src/lib/components/screen-link.js.map +1 -0
- package/src/lib/components/search-box.d.ts +41 -0
- package/src/lib/components/search-box.js +125 -0
- package/src/lib/components/search-box.js.map +1 -0
- package/src/lib/components/section.d.ts +56 -0
- package/src/lib/components/section.js +132 -0
- package/src/lib/components/section.js.map +1 -0
- package/src/lib/components/stack.d.ts +55 -0
- package/src/lib/components/stack.js +309 -0
- package/src/lib/components/stack.js.map +1 -0
- package/src/lib/components/tabs.d.ts +288 -0
- package/src/lib/components/tabs.js +788 -0
- package/src/lib/components/tabs.js.map +1 -0
- package/src/lib/components/theme-mode-switcher.d.ts +38 -0
- package/src/lib/components/theme-mode-switcher.js +168 -0
- package/src/lib/components/theme-mode-switcher.js.map +1 -0
- package/src/lib/components/toolbar.d.ts +37 -0
- package/src/lib/components/toolbar.js +117 -0
- package/src/lib/components/toolbar.js.map +1 -0
- package/src/lib/components/typography.d.ts +33 -0
- package/src/lib/components/typography.js +433 -0
- package/src/lib/components/typography.js.map +1 -0
- package/src/lib/components/video-lightbox-controls.d.ts +131 -0
- package/src/lib/components/video-lightbox-controls.js +536 -0
- package/src/lib/components/video-lightbox-controls.js.map +1 -0
- package/src/lib/components/video-lightbox.d.ts +60 -0
- package/src/lib/components/video-lightbox.js +247 -0
- package/src/lib/components/video-lightbox.js.map +1 -0
- package/src/lib/components/video-playback-beacon.d.ts +80 -0
- package/src/lib/components/video-playback-beacon.js +128 -0
- package/src/lib/components/video-playback-beacon.js.map +1 -0
- package/src/lib/components/video-player-frame.d.ts +58 -0
- package/src/lib/components/video-player-frame.js +51 -0
- package/src/lib/components/video-player-frame.js.map +1 -0
- package/src/lib/components/video.d.ts +220 -0
- package/src/lib/components/video.js +874 -0
- package/src/lib/components/video.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +17 -0
- package/src/lib/constants/bundle-common.js +18 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/field-presets.d.ts +93 -0
- package/src/lib/constants/field-presets.js +248 -0
- package/src/lib/constants/field-presets.js.map +1 -0
- package/src/lib/plugin.d.ts +80 -0
- package/src/lib/plugin.js +599 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/utils/author-html-label.d.ts +73 -0
- package/src/lib/utils/author-html-label.js +89 -0
- package/src/lib/utils/author-html-label.js.map +1 -0
- package/src/lib/utils/drop-cleared-props.d.ts +18 -0
- package/src/lib/utils/drop-cleared-props.js +74 -0
- package/src/lib/utils/drop-cleared-props.js.map +1 -0
- package/src/lib/utils/element-picker.d.ts +99 -0
- package/src/lib/utils/element-picker.js +140 -0
- package/src/lib/utils/element-picker.js.map +1 -0
- package/src/lib/utils/generate-preset-id.d.ts +19 -0
- package/src/lib/utils/generate-preset-id.js +25 -0
- package/src/lib/utils/generate-preset-id.js.map +1 -0
- package/src/lib/utils/link-target-props.d.ts +53 -0
- package/src/lib/utils/link-target-props.js +53 -0
- package/src/lib/utils/link-target-props.js.map +1 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
/**
|
|
5
|
+
* @license
|
|
6
|
+
* Copyright 2026 Aglyn LLC
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
20
|
+
import { mdiFormatColorHighlight, mdiFormatColorText } from "@aglyn/shared-data-mdi";
|
|
21
|
+
import MuiBox from "@mui/material/Box";
|
|
22
|
+
import { forwardRef } from "react";
|
|
23
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
24
|
+
import { FIELD_TEXT_CONTENT } from "../constants/field-presets.js";
|
|
25
|
+
import { authorHtmlLabel } from "../utils/author-html-label.js";
|
|
26
|
+
import { generatePresetId } from "../utils/generate-preset-id.js";
|
|
27
|
+
// Component ids are persisted in screen documents; never rename.
|
|
28
|
+
export const ID = 'muiInlineText';
|
|
29
|
+
/**
|
|
30
|
+
* Inline elements the run may render as. An allow-list rather than a
|
|
31
|
+
* free-text field, for the same reason Box's is (AGL-1201): `element` is
|
|
32
|
+
* persisted and rendered verbatim into every visitor's page, so a typed
|
|
33
|
+
* value would let an author put `script`/`iframe` there.
|
|
34
|
+
*
|
|
35
|
+
* All five are phrasing content, so a run is always legal inside a
|
|
36
|
+
* paragraph — which is the whole point of the element.
|
|
37
|
+
*/ export const INLINE_TEXT_ELEMENTS = [
|
|
38
|
+
'span',
|
|
39
|
+
'strong',
|
|
40
|
+
'em',
|
|
41
|
+
'mark',
|
|
42
|
+
'small'
|
|
43
|
+
];
|
|
44
|
+
/**
|
|
45
|
+
* Theme palette paths, never raw hexes: the design's `text/muted` and
|
|
46
|
+
* `text/primary` tokens ARE `text.secondary` / `text.primary`, and a
|
|
47
|
+
* hardcoded `#757575` would ignore the site's theme (and dark mode).
|
|
48
|
+
*
|
|
49
|
+
* Every value is a real sentinel — an option value of `''` is stripped
|
|
50
|
+
* before save and the pick silently reverts on reload (AGL-1191), so
|
|
51
|
+
* "inherit" has to be spelled out rather than left blank.
|
|
52
|
+
*/ const TONE_COLOR = {
|
|
53
|
+
inherit: undefined,
|
|
54
|
+
primary: 'text.primary',
|
|
55
|
+
secondary: 'text.secondary',
|
|
56
|
+
disabled: 'text.disabled',
|
|
57
|
+
accent: 'primary.main',
|
|
58
|
+
accentAlt: 'secondary.main',
|
|
59
|
+
success: 'success.main',
|
|
60
|
+
warning: 'warning.main',
|
|
61
|
+
error: 'error.main'
|
|
62
|
+
};
|
|
63
|
+
/** Named weights so the field is a pick, not a number to remember. */ const FONT_WEIGHT = {
|
|
64
|
+
inherit: undefined,
|
|
65
|
+
regular: 400,
|
|
66
|
+
medium: 500,
|
|
67
|
+
semibold: 600,
|
|
68
|
+
bold: 700
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* `text-decoration` PROPAGATES — it is not inherited. An ancestor's
|
|
72
|
+
* underline (a Screen Link, a struck-through block) is painted straight
|
|
73
|
+
* across every in-flow inline descendant, and `text-decoration: none` on
|
|
74
|
+
* the descendant CANNOT remove it. Only an element that is not an in-flow
|
|
75
|
+
* non-atomic inline box escapes the propagation, which is why "None" also
|
|
76
|
+
* switches the run to `inline-block`: an atomic inline box is not painted
|
|
77
|
+
* through.
|
|
78
|
+
*
|
|
79
|
+
* That costs line-breaking — an inline-block will not break across lines —
|
|
80
|
+
* so it is opt-in rather than the default, and the field says so. The
|
|
81
|
+
* default, `inherit`, is a plain `display: inline` run that flows and wraps
|
|
82
|
+
* with the rest of the sentence.
|
|
83
|
+
*/ const DECORATION_SX = {
|
|
84
|
+
inherit: {},
|
|
85
|
+
none: {
|
|
86
|
+
display: 'inline-block',
|
|
87
|
+
textDecoration: 'none'
|
|
88
|
+
},
|
|
89
|
+
underline: {
|
|
90
|
+
textDecoration: 'underline'
|
|
91
|
+
},
|
|
92
|
+
lineThrough: {
|
|
93
|
+
textDecoration: 'line-through'
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* One run of text inside a sentence (AGL-1235).
|
|
98
|
+
*
|
|
99
|
+
* The gap this fills: `muiTypography` is `textEditable`, therefore a leaf —
|
|
100
|
+
* `nodeAcceptsChildren` reports false, so no span can be nested inside it.
|
|
101
|
+
* A statement whose argument lives in an emphasised phrase ("Aglyn commerce
|
|
102
|
+
* is **part of the platform**") could not be authored at all; the whole line
|
|
103
|
+
* was one flat colour.
|
|
104
|
+
*
|
|
105
|
+
* This is a leaf too, deliberately: the shape that renders correctly is a
|
|
106
|
+
* block container holding SIBLING inline runs, not a nested span. Sibling
|
|
107
|
+
* runs flow and wrap as a single paragraph, so the sentence breaks
|
|
108
|
+
* naturally with the emphasis landing in the right place. Drop a Box as
|
|
109
|
+
* `p`, then one of these per style change.
|
|
110
|
+
*/ const InlineText = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
111
|
+
var _DECORATION_SX_decoration, _authorHtmlLabel;
|
|
112
|
+
const { element, tone, weight, decoration, children, sx, html } = props, rest = _object_without_properties_loose(props, [
|
|
113
|
+
"element",
|
|
114
|
+
"tone",
|
|
115
|
+
"weight",
|
|
116
|
+
"decoration",
|
|
117
|
+
"children",
|
|
118
|
+
"sx",
|
|
119
|
+
"html"
|
|
120
|
+
]);
|
|
121
|
+
const component = INLINE_TEXT_ELEMENTS.includes(element) ? element : 'span';
|
|
122
|
+
// Node styles ride the renderer-merged sx; recompose rather than spread
|
|
123
|
+
// (the stack.ts/link-box.tsx pattern). Writing an `sx` literal after the
|
|
124
|
+
// props spread would REPLACE the author's styles silently — the defect
|
|
125
|
+
// class `aglyn/no-sx-after-spread` guards (AGL-1240/1284).
|
|
126
|
+
const nodeSx = Array.isArray(sx) ? sx : sx ? [
|
|
127
|
+
sx
|
|
128
|
+
] : [];
|
|
129
|
+
// A cleared attribute persists as null, so every lookup below must miss
|
|
130
|
+
// rather than throw; `Record[null]` is simply undefined.
|
|
131
|
+
const color = TONE_COLOR[tone];
|
|
132
|
+
const fontWeight = FONT_WEIGHT[weight];
|
|
133
|
+
return /*#__PURE__*/ _jsx(MuiBox, _extends({
|
|
134
|
+
ref: ref,
|
|
135
|
+
component: component
|
|
136
|
+
}, rest, {
|
|
137
|
+
// Order matters: the baseline first, then the declared attributes,
|
|
138
|
+
// then the author's node styles last so the Styles panel always wins.
|
|
139
|
+
sx: [
|
|
140
|
+
{
|
|
141
|
+
display: 'inline'
|
|
142
|
+
},
|
|
143
|
+
color ? {
|
|
144
|
+
color
|
|
145
|
+
} : {},
|
|
146
|
+
fontWeight ? {
|
|
147
|
+
fontWeight
|
|
148
|
+
} : {},
|
|
149
|
+
(_DECORATION_SX_decoration = DECORATION_SX[decoration]) != null ? _DECORATION_SX_decoration : {},
|
|
150
|
+
...nodeSx
|
|
151
|
+
],
|
|
152
|
+
children: (_authorHtmlLabel = authorHtmlLabel(html)) != null ? _authorHtmlLabel : children
|
|
153
|
+
}));
|
|
154
|
+
});
|
|
155
|
+
InlineText.displayName = 'AglynInlineText';
|
|
156
|
+
export const schema = {
|
|
157
|
+
$id: ID,
|
|
158
|
+
pluginId: BUNDLE_ID,
|
|
159
|
+
displayName: 'Inline Text',
|
|
160
|
+
description: 'One run of text inside a sentence — put several side by side in a ' + 'paragraph to emphasise a phrase without breaking the line.',
|
|
161
|
+
category: Aglyn.ComponentCategory.TEXT,
|
|
162
|
+
icon: {
|
|
163
|
+
path: mdiFormatColorText.path,
|
|
164
|
+
sx: {
|
|
165
|
+
color: '#057822'
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
flags: {
|
|
169
|
+
// The run IS its text: edited inline on the canvas, like Typography.
|
|
170
|
+
textEditable: Aglyn.FEATURE_FLAG.ENABLED,
|
|
171
|
+
richTextEditable: Aglyn.FEATURE_FLAG.ENABLED
|
|
172
|
+
},
|
|
173
|
+
// Emphasis only (AGL-2557), for a different reason than the controls: this
|
|
174
|
+
// run is not interactive, it is `display: inline`. Every element it may
|
|
175
|
+
// render as is phrasing content — that is the guarantee INLINE_TEXT_ELEMENTS
|
|
176
|
+
// exists to make — so a list inside one is a block in an inline box, which
|
|
177
|
+
// the parser lifts straight back out of the enclosing paragraph. Links stay
|
|
178
|
+
// with Screen Link, whose job is a resolved target rather than a typed href.
|
|
179
|
+
richTextCommands: [
|
|
180
|
+
Aglyn.RICH_TEXT_COMMANDS.EMPHASIS
|
|
181
|
+
],
|
|
182
|
+
attributes: [
|
|
183
|
+
FIELD_TEXT_CONTENT,
|
|
184
|
+
{
|
|
185
|
+
name: 'element',
|
|
186
|
+
label: 'Component',
|
|
187
|
+
description: 'The DOM element this run renders as. `strong` and `em` carry ' + 'meaning for screen readers and search engines; `mark` marks a ' + 'highlighted phrase; `span` is purely visual.',
|
|
188
|
+
component: Aglyn.FieldComponentType.SELECT,
|
|
189
|
+
options: INLINE_TEXT_ELEMENTS.map((value)=>({
|
|
190
|
+
value,
|
|
191
|
+
label: value
|
|
192
|
+
}))
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: 'tone',
|
|
196
|
+
label: 'Color',
|
|
197
|
+
description: "Palette token for this run. Two-tone text is a muted sentence " + 'with one run set to Primary (or Accent) — theme tokens, so it ' + 'still reads correctly in dark mode.',
|
|
198
|
+
component: Aglyn.FieldComponentType.SELECT,
|
|
199
|
+
options: [
|
|
200
|
+
{
|
|
201
|
+
value: 'inherit',
|
|
202
|
+
label: 'Inherit'
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
value: 'primary',
|
|
206
|
+
label: 'Text primary'
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
value: 'secondary',
|
|
210
|
+
label: 'Text muted'
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
value: 'disabled',
|
|
214
|
+
label: 'Text disabled'
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
value: 'accent',
|
|
218
|
+
label: 'Accent'
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
value: 'accentAlt',
|
|
222
|
+
label: 'Accent alternate'
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
value: 'success',
|
|
226
|
+
label: 'Success'
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
value: 'warning',
|
|
230
|
+
label: 'Warning'
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
value: 'error',
|
|
234
|
+
label: 'Error'
|
|
235
|
+
}
|
|
236
|
+
]
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: 'weight',
|
|
240
|
+
label: 'Weight',
|
|
241
|
+
description: 'Font weight for this run only.',
|
|
242
|
+
component: Aglyn.FieldComponentType.SELECT,
|
|
243
|
+
options: [
|
|
244
|
+
{
|
|
245
|
+
value: 'inherit',
|
|
246
|
+
label: 'Inherit'
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
value: 'regular',
|
|
250
|
+
label: 'Regular'
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
value: 'medium',
|
|
254
|
+
label: 'Medium'
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
value: 'semibold',
|
|
258
|
+
label: 'Semi bold'
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
value: 'bold',
|
|
262
|
+
label: 'Bold'
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
name: 'decoration',
|
|
268
|
+
label: 'Underline / strike',
|
|
269
|
+
description: 'Inherit follows the surrounding text, including a link\'s ' + 'underline — an underline PROPAGATES down and cannot be switched ' + 'off from inside. None does switch it off, at the cost of the run ' + 'no longer breaking across lines, so keep it to a short phrase.',
|
|
270
|
+
component: Aglyn.FieldComponentType.SELECT,
|
|
271
|
+
options: [
|
|
272
|
+
{
|
|
273
|
+
value: 'inherit',
|
|
274
|
+
label: 'Inherit'
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
value: 'none',
|
|
278
|
+
label: 'None (does not wrap)'
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
value: 'underline',
|
|
282
|
+
label: 'Underline'
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
value: 'lineThrough',
|
|
286
|
+
label: 'Strikethrough'
|
|
287
|
+
}
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
]
|
|
291
|
+
};
|
|
292
|
+
export const presets = [
|
|
293
|
+
{
|
|
294
|
+
$id: generatePresetId(ID),
|
|
295
|
+
type: Aglyn.NodeType.PRESET,
|
|
296
|
+
displayName: 'Inline Text',
|
|
297
|
+
pluginId: BUNDLE_ID,
|
|
298
|
+
description: 'One run of text inside a sentence',
|
|
299
|
+
category: Aglyn.ComponentCategory.TEXT,
|
|
300
|
+
icon: schema.icon,
|
|
301
|
+
data: {
|
|
302
|
+
$id: null,
|
|
303
|
+
componentId: ID,
|
|
304
|
+
pluginId: BUNDLE_ID,
|
|
305
|
+
props: {
|
|
306
|
+
element: 'span',
|
|
307
|
+
children: 'Inline text'
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
$id: generatePresetId(ID, 'emphasis'),
|
|
313
|
+
type: Aglyn.NodeType.PRESET,
|
|
314
|
+
displayName: 'Emphasised Text',
|
|
315
|
+
pluginId: BUNDLE_ID,
|
|
316
|
+
description: 'A phrase picked out of a muted sentence',
|
|
317
|
+
category: Aglyn.ComponentCategory.TEXT,
|
|
318
|
+
icon: {
|
|
319
|
+
path: mdiFormatColorHighlight.path,
|
|
320
|
+
sx: {
|
|
321
|
+
color: '#057822'
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
data: {
|
|
325
|
+
$id: null,
|
|
326
|
+
componentId: ID,
|
|
327
|
+
pluginId: BUNDLE_ID,
|
|
328
|
+
props: {
|
|
329
|
+
element: 'strong',
|
|
330
|
+
tone: 'primary',
|
|
331
|
+
weight: 'bold',
|
|
332
|
+
children: 'the emphasised phrase'
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
// The whole shape in one drop (AGL-1235): the reason the emphasis was
|
|
338
|
+
// never authored is that assembling it by hand meant a container, three
|
|
339
|
+
// runs and a colour on each. This is that assembly, ready to retype.
|
|
340
|
+
$id: generatePresetId(ID, 'statement'),
|
|
341
|
+
type: Aglyn.NodeType.PRESET,
|
|
342
|
+
displayName: 'Two-tone Statement',
|
|
343
|
+
pluginId: BUNDLE_ID,
|
|
344
|
+
description: 'A muted sentence with one phrase emphasised',
|
|
345
|
+
category: Aglyn.ComponentCategory.TEXT,
|
|
346
|
+
icon: {
|
|
347
|
+
path: mdiFormatColorHighlight.path,
|
|
348
|
+
sx: {
|
|
349
|
+
color: '#057822'
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
data: {
|
|
353
|
+
$id: null,
|
|
354
|
+
// A real `<p>`, not a div: the runs are phrasing content, so the
|
|
355
|
+
// paragraph is the honest container and screen readers get a
|
|
356
|
+
// sentence rather than three unrelated fragments.
|
|
357
|
+
componentId: 'muiBox',
|
|
358
|
+
pluginId: BUNDLE_ID,
|
|
359
|
+
props: {
|
|
360
|
+
component: 'p'
|
|
361
|
+
},
|
|
362
|
+
// Node-level sx (AGL-1346) — the record the Styles panel edits.
|
|
363
|
+
sx: {
|
|
364
|
+
marginTop: 0,
|
|
365
|
+
marginRight: 0,
|
|
366
|
+
marginBottom: 0,
|
|
367
|
+
marginLeft: 0
|
|
368
|
+
},
|
|
369
|
+
nodes: [
|
|
370
|
+
{
|
|
371
|
+
$id: null,
|
|
372
|
+
componentId: ID,
|
|
373
|
+
pluginId: BUNDLE_ID,
|
|
374
|
+
props: {
|
|
375
|
+
element: 'span',
|
|
376
|
+
tone: 'secondary',
|
|
377
|
+
children: 'Everything you build is '
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
$id: null,
|
|
382
|
+
componentId: ID,
|
|
383
|
+
pluginId: BUNDLE_ID,
|
|
384
|
+
props: {
|
|
385
|
+
element: 'strong',
|
|
386
|
+
tone: 'primary',
|
|
387
|
+
weight: 'bold',
|
|
388
|
+
children: 'part of the platform'
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
$id: null,
|
|
393
|
+
componentId: ID,
|
|
394
|
+
pluginId: BUNDLE_ID,
|
|
395
|
+
props: {
|
|
396
|
+
element: 'span',
|
|
397
|
+
tone: 'secondary',
|
|
398
|
+
children: ', not bolted onto it.'
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
]
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
];
|
|
405
|
+
export default InlineText;
|
|
406
|
+
|
|
407
|
+
//# sourceMappingURL=inline-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/inline-text.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 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 * as Aglyn from '@aglyn/aglyn'\nimport { mdiFormatColorHighlight, mdiFormatColorText } from '@aglyn/shared-data-mdi'\nimport MuiBox from '@mui/material/Box'\nimport type { SxProps } from '@mui/material/styles'\nimport { forwardRef, type ReactNode } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { FIELD_TEXT_CONTENT } from '../constants/field-presets'\nimport { authorHtmlLabel } from '../utils/author-html-label'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'muiInlineText'\n\n/**\n * Inline elements the run may render as. An allow-list rather than a\n * free-text field, for the same reason Box's is (AGL-1201): `element` is\n * persisted and rendered verbatim into every visitor's page, so a typed\n * value would let an author put `script`/`iframe` there.\n *\n * All five are phrasing content, so a run is always legal inside a\n * paragraph — which is the whole point of the element.\n */\nexport const INLINE_TEXT_ELEMENTS = [\n 'span',\n 'strong',\n 'em',\n 'mark',\n 'small',\n] as const\nexport type InlineTextElement = (typeof INLINE_TEXT_ELEMENTS)[number]\n\n/**\n * Theme palette paths, never raw hexes: the design's `text/muted` and\n * `text/primary` tokens ARE `text.secondary` / `text.primary`, and a\n * hardcoded `#757575` would ignore the site's theme (and dark mode).\n *\n * Every value is a real sentinel — an option value of `''` is stripped\n * before save and the pick silently reverts on reload (AGL-1191), so\n * \"inherit\" has to be spelled out rather than left blank.\n */\nconst TONE_COLOR: Record<string, string> = {\n inherit: undefined,\n primary: 'text.primary',\n secondary: 'text.secondary',\n disabled: 'text.disabled',\n accent: 'primary.main',\n accentAlt: 'secondary.main',\n success: 'success.main',\n warning: 'warning.main',\n error: 'error.main',\n}\n\n/** Named weights so the field is a pick, not a number to remember. */\nconst FONT_WEIGHT: Record<string, number> = {\n inherit: undefined,\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n}\n\n/**\n * `text-decoration` PROPAGATES — it is not inherited. An ancestor's\n * underline (a Screen Link, a struck-through block) is painted straight\n * across every in-flow inline descendant, and `text-decoration: none` on\n * the descendant CANNOT remove it. Only an element that is not an in-flow\n * non-atomic inline box escapes the propagation, which is why \"None\" also\n * switches the run to `inline-block`: an atomic inline box is not painted\n * through.\n *\n * That costs line-breaking — an inline-block will not break across lines —\n * so it is opt-in rather than the default, and the field says so. The\n * default, `inherit`, is a plain `display: inline` run that flows and wraps\n * with the rest of the sentence.\n */\nconst DECORATION_SX: Record<string, Record<string, string>> = {\n inherit: {},\n none: { display: 'inline-block', textDecoration: 'none' },\n underline: { textDecoration: 'underline' },\n lineThrough: { textDecoration: 'line-through' },\n}\n\nexport interface InlineTextProps {\n /** The DOM element rendered; defaults to `span`. */\n element?: InlineTextElement\n /** Palette token key from {@link TONE_COLOR}. */\n tone?: string\n /** Named weight key from {@link FONT_WEIGHT}. */\n weight?: string\n /** Decoration behaviour key from {@link DECORATION_SX}. */\n decoration?: string\n /**\n * Authored node styles, handed over by the renderer rather than typed\n * into an attribute. Declared because the merge below reads it —\n * undeclared, no typed caller could style a run (AGL-1323).\n */\n sx?: SxProps\n /**\n * Sanitized emphasis markup for the run, written by the inline editor's\n * rich mode (AGL-2557). `children` keeps the plain-text reading of it, and\n * is what every surface that cannot render markup falls back to.\n */\n html?: string\n /** The text of this run; edited inline on the canvas. */\n children?: ReactNode\n}\n\n/**\n * One run of text inside a sentence (AGL-1235).\n *\n * The gap this fills: `muiTypography` is `textEditable`, therefore a leaf —\n * `nodeAcceptsChildren` reports false, so no span can be nested inside it.\n * A statement whose argument lives in an emphasised phrase (\"Aglyn commerce\n * is **part of the platform**\") could not be authored at all; the whole line\n * was one flat colour.\n *\n * This is a leaf too, deliberately: the shape that renders correctly is a\n * block container holding SIBLING inline runs, not a nested span. Sibling\n * runs flow and wrap as a single paragraph, so the sentence breaks\n * naturally with the emphasis landing in the right place. Drop a Box as\n * `p`, then one of these per style change.\n */\nconst InlineText = forwardRef<HTMLElement, InlineTextProps>((props, ref) => {\n const { element, tone, weight, decoration, children, sx, html, ...rest } =\n props\n const component = INLINE_TEXT_ELEMENTS.includes(element as InlineTextElement)\n ? (element as InlineTextElement)\n : 'span'\n // Node styles ride the renderer-merged sx; recompose rather than spread\n // (the stack.ts/link-box.tsx pattern). Writing an `sx` literal after the\n // props spread would REPLACE the author's styles silently — the defect\n // class `aglyn/no-sx-after-spread` guards (AGL-1240/1284).\n const nodeSx = Array.isArray(sx) ? sx : sx ? [sx] : []\n // A cleared attribute persists as null, so every lookup below must miss\n // rather than throw; `Record[null]` is simply undefined.\n const color = TONE_COLOR[tone]\n const fontWeight = FONT_WEIGHT[weight]\n return (\n <MuiBox\n ref={ref}\n component={component}\n {...rest}\n // Order matters: the baseline first, then the declared attributes,\n // then the author's node styles last so the Styles panel always wins.\n sx={[\n { display: 'inline' },\n color ? { color } : {},\n fontWeight ? { fontWeight } : {},\n DECORATION_SX[decoration] ?? {},\n ...nodeSx,\n ]}\n >\n {authorHtmlLabel(html) ?? children}\n </MuiBox>\n )\n})\nInlineText.displayName = 'AglynInlineText'\n\nexport const schema: Aglyn.ComponentSchema<InlineTextProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Inline Text',\n description:\n 'One run of text inside a sentence — put several side by side in a ' +\n 'paragraph to emphasise a phrase without breaking the line.',\n category: Aglyn.ComponentCategory.TEXT,\n icon: { path: mdiFormatColorText.path, sx: { color: '#057822' } },\n flags: {\n // The run IS its text: edited inline on the canvas, like Typography.\n textEditable: Aglyn.FEATURE_FLAG.ENABLED,\n richTextEditable: Aglyn.FEATURE_FLAG.ENABLED,\n },\n // Emphasis only (AGL-2557), for a different reason than the controls: this\n // run is not interactive, it is `display: inline`. Every element it may\n // render as is phrasing content — that is the guarantee INLINE_TEXT_ELEMENTS\n // exists to make — so a list inside one is a block in an inline box, which\n // the parser lifts straight back out of the enclosing paragraph. Links stay\n // with Screen Link, whose job is a resolved target rather than a typed href.\n richTextCommands: [Aglyn.RICH_TEXT_COMMANDS.EMPHASIS],\n attributes: [\n FIELD_TEXT_CONTENT,\n {\n name: 'element',\n label: 'Component',\n description:\n 'The DOM element this run renders as. `strong` and `em` carry ' +\n 'meaning for screen readers and search engines; `mark` marks a ' +\n 'highlighted phrase; `span` is purely visual.',\n component: Aglyn.FieldComponentType.SELECT,\n options: INLINE_TEXT_ELEMENTS.map((value) => ({ value, label: value })),\n },\n {\n name: 'tone',\n label: 'Color',\n description:\n \"Palette token for this run. Two-tone text is a muted sentence \" +\n 'with one run set to Primary (or Accent) — theme tokens, so it ' +\n 'still reads correctly in dark mode.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'primary', label: 'Text primary' },\n { value: 'secondary', label: 'Text muted' },\n { value: 'disabled', label: 'Text disabled' },\n { value: 'accent', label: 'Accent' },\n { value: 'accentAlt', label: 'Accent alternate' },\n { value: 'success', label: 'Success' },\n { value: 'warning', label: 'Warning' },\n { value: 'error', label: 'Error' },\n ],\n },\n {\n name: 'weight',\n label: 'Weight',\n description: 'Font weight for this run only.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'regular', label: 'Regular' },\n { value: 'medium', label: 'Medium' },\n { value: 'semibold', label: 'Semi bold' },\n { value: 'bold', label: 'Bold' },\n ],\n },\n {\n name: 'decoration',\n label: 'Underline / strike',\n description:\n 'Inherit follows the surrounding text, including a link\\'s ' +\n 'underline — an underline PROPAGATES down and cannot be switched ' +\n 'off from inside. None does switch it off, at the cost of the run ' +\n 'no longer breaking across lines, so keep it to a short phrase.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'none', label: 'None (does not wrap)' },\n { value: 'underline', label: 'Underline' },\n { value: 'lineThrough', label: 'Strikethrough' },\n ],\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Inline Text',\n pluginId: BUNDLE_ID,\n description: 'One run of text inside a sentence',\n category: Aglyn.ComponentCategory.TEXT,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { element: 'span', children: 'Inline text' },\n },\n },\n {\n $id: generatePresetId(ID, 'emphasis'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Emphasised Text',\n pluginId: BUNDLE_ID,\n description: 'A phrase picked out of a muted sentence',\n category: Aglyn.ComponentCategory.TEXT,\n icon: { path: mdiFormatColorHighlight.path, sx: { color: '#057822' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: {\n element: 'strong',\n tone: 'primary',\n weight: 'bold',\n children: 'the emphasised phrase',\n },\n },\n },\n {\n // The whole shape in one drop (AGL-1235): the reason the emphasis was\n // never authored is that assembling it by hand meant a container, three\n // runs and a colour on each. This is that assembly, ready to retype.\n $id: generatePresetId(ID, 'statement'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Two-tone Statement',\n pluginId: BUNDLE_ID,\n description: 'A muted sentence with one phrase emphasised',\n category: Aglyn.ComponentCategory.TEXT,\n icon: { path: mdiFormatColorHighlight.path, sx: { color: '#057822' } },\n data: {\n $id: null,\n // A real `<p>`, not a div: the runs are phrasing content, so the\n // paragraph is the honest container and screen readers get a\n // sentence rather than three unrelated fragments.\n componentId: 'muiBox',\n pluginId: BUNDLE_ID,\n props: { component: 'p' },\n // Node-level sx (AGL-1346) — the record the Styles panel edits.\n sx: { marginTop: 0, marginRight: 0, marginBottom: 0, marginLeft: 0 },\n nodes: [\n {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: {\n element: 'span',\n tone: 'secondary',\n children: 'Everything you build is ',\n },\n },\n {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: {\n element: 'strong',\n tone: 'primary',\n weight: 'bold',\n children: 'part of the platform',\n },\n },\n {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: {\n element: 'span',\n tone: 'secondary',\n children: ', not bolted onto it.',\n },\n },\n ],\n },\n },\n]\n\nexport default InlineText\n"],"names":["Aglyn","mdiFormatColorHighlight","mdiFormatColorText","MuiBox","forwardRef","BUNDLE_ID","FIELD_TEXT_CONTENT","authorHtmlLabel","generatePresetId","ID","INLINE_TEXT_ELEMENTS","TONE_COLOR","inherit","undefined","primary","secondary","disabled","accent","accentAlt","success","warning","error","FONT_WEIGHT","regular","medium","semibold","bold","DECORATION_SX","none","display","textDecoration","underline","lineThrough","InlineText","props","ref","element","tone","weight","decoration","children","sx","html","rest","component","includes","nodeSx","Array","isArray","color","fontWeight","displayName","schema","$id","pluginId","description","category","ComponentCategory","TEXT","icon","path","flags","textEditable","FEATURE_FLAG","ENABLED","richTextEditable","richTextCommands","RICH_TEXT_COMMANDS","EMPHASIS","attributes","name","label","FieldComponentType","SELECT","options","map","value","presets","type","NodeType","PRESET","data","componentId","marginTop","marginRight","marginBottom","marginLeft","nodes"],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import * as Aglyn from '@aglyn/aglyn';
|
|
18
|
+
export declare const ID: Aglyn.ComponentId;
|
|
19
|
+
export interface LanguageSwitcherProps {
|
|
20
|
+
/** 'text' shows locale codes; 'buttons' renders outlined buttons. */
|
|
21
|
+
variant?: 'text' | 'buttons';
|
|
22
|
+
/** Uppercase the locale codes (EN / ES). */
|
|
23
|
+
uppercase?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Language switcher (AGL-164): renders one link per translation of the
|
|
27
|
+
* CURRENT screen, resolved from ScreenLinkContext (`localeVariants` +
|
|
28
|
+
* routing map), so it works inside shared layouts. Shows a placeholder in
|
|
29
|
+
* the editor when the screen has no variants; renders nothing on the live
|
|
30
|
+
* site in that case.
|
|
31
|
+
*/
|
|
32
|
+
declare const LanguageSwitcher: import("react").ForwardRefExoticComponent<LanguageSwitcherProps & import("react").RefAttributes<HTMLElement>>;
|
|
33
|
+
export declare const schema: Aglyn.ComponentSchema<LanguageSwitcherProps>;
|
|
34
|
+
export declare const presets: Aglyn.PresetSchema[];
|
|
35
|
+
export default LanguageSwitcher;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
/**
|
|
5
|
+
* @license
|
|
6
|
+
* Copyright 2026 Aglyn LLC
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
20
|
+
import { mdiTranslate } from "@aglyn/shared-data-mdi";
|
|
21
|
+
import { AppLink } from "@aglyn/shared-ui-jsx";
|
|
22
|
+
import Button from "@mui/material/Button";
|
|
23
|
+
import Stack from "@mui/material/Stack";
|
|
24
|
+
import { forwardRef, useContext } from "react";
|
|
25
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
26
|
+
import { generatePresetId } from "../utils/generate-preset-id.js";
|
|
27
|
+
// Component ids are persisted in screen documents; never rename.
|
|
28
|
+
export const ID = 'languageSwitcher';
|
|
29
|
+
/**
|
|
30
|
+
* Language switcher (AGL-164): renders one link per translation of the
|
|
31
|
+
* CURRENT screen, resolved from ScreenLinkContext (`localeVariants` +
|
|
32
|
+
* routing map), so it works inside shared layouts. Shows a placeholder in
|
|
33
|
+
* the editor when the screen has no variants; renders nothing on the live
|
|
34
|
+
* site in that case.
|
|
35
|
+
*/ const LanguageSwitcher = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
36
|
+
const { variant, uppercase } = props, rest = _object_without_properties_loose(props, [
|
|
37
|
+
"variant",
|
|
38
|
+
"uppercase"
|
|
39
|
+
]);
|
|
40
|
+
// Node styles ride the renderer-merged sx; recompose (stack.ts pattern).
|
|
41
|
+
const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
|
|
42
|
+
props['sx']
|
|
43
|
+
];
|
|
44
|
+
const { screens, localeVariants, currentLocale, suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
|
|
45
|
+
const entries = Object.entries(localeVariants != null ? localeVariants : {}).filter(([, screenId])=>(screens == null ? void 0 : screens[screenId]) != null);
|
|
46
|
+
const format = (locale)=>uppercase === false ? locale : locale.toUpperCase();
|
|
47
|
+
if (!entries.length) {
|
|
48
|
+
// Editor-only placeholder; invisible on the live site.
|
|
49
|
+
if (!suppressNavigation) return null;
|
|
50
|
+
return /*#__PURE__*/ _jsx(Stack, _extends({
|
|
51
|
+
ref: ref,
|
|
52
|
+
direction: "row",
|
|
53
|
+
spacing: 1
|
|
54
|
+
}, rest, {
|
|
55
|
+
sx: [
|
|
56
|
+
{
|
|
57
|
+
alignItems: 'center',
|
|
58
|
+
border: '1px dashed',
|
|
59
|
+
borderColor: 'divider',
|
|
60
|
+
borderRadius: 1,
|
|
61
|
+
px: 1.5,
|
|
62
|
+
py: 0.5,
|
|
63
|
+
color: 'text.secondary',
|
|
64
|
+
fontSize: 12,
|
|
65
|
+
fontFamily: 'system-ui, sans-serif'
|
|
66
|
+
},
|
|
67
|
+
...nodeSx
|
|
68
|
+
],
|
|
69
|
+
children: 'Language switcher — set screen translations'
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
return /*#__PURE__*/ _jsxs(Stack, _extends({
|
|
73
|
+
ref: ref,
|
|
74
|
+
direction: "row",
|
|
75
|
+
spacing: 0.5
|
|
76
|
+
}, rest, {
|
|
77
|
+
sx: [
|
|
78
|
+
{
|
|
79
|
+
alignItems: 'center'
|
|
80
|
+
},
|
|
81
|
+
...nodeSx
|
|
82
|
+
],
|
|
83
|
+
children: [
|
|
84
|
+
currentLocale ? /*#__PURE__*/ _jsx(Button, {
|
|
85
|
+
size: "small",
|
|
86
|
+
variant: "text",
|
|
87
|
+
disabled: true,
|
|
88
|
+
children: format(currentLocale)
|
|
89
|
+
}) : null,
|
|
90
|
+
entries.map(([locale, screenId])=>{
|
|
91
|
+
const path = screens == null ? void 0 : screens[screenId];
|
|
92
|
+
const href = path != null ? Aglyn.screenRoutePathToUrl(path) : undefined;
|
|
93
|
+
if (!href || suppressNavigation) {
|
|
94
|
+
return /*#__PURE__*/ _jsx(Button, {
|
|
95
|
+
size: "small",
|
|
96
|
+
variant: "text",
|
|
97
|
+
children: format(locale)
|
|
98
|
+
}, locale);
|
|
99
|
+
}
|
|
100
|
+
return /*#__PURE__*/ _jsx(AppLink, {
|
|
101
|
+
componentVariant: "button",
|
|
102
|
+
href: href,
|
|
103
|
+
size: "small",
|
|
104
|
+
variant: variant === 'buttons' ? 'outlined' : 'text',
|
|
105
|
+
children: format(locale)
|
|
106
|
+
}, locale);
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
}));
|
|
110
|
+
});
|
|
111
|
+
LanguageSwitcher.displayName = 'LanguageSwitcher';
|
|
112
|
+
export const schema = {
|
|
113
|
+
$id: ID,
|
|
114
|
+
pluginId: BUNDLE_ID,
|
|
115
|
+
displayName: 'Language Switcher',
|
|
116
|
+
description: "Links between this screen's translations. It hides itself when there are none.",
|
|
117
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
118
|
+
icon: {
|
|
119
|
+
path: mdiTranslate.path,
|
|
120
|
+
sx: {
|
|
121
|
+
color: '#2196f3'
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
flags: {
|
|
125
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
126
|
+
},
|
|
127
|
+
attributes: [
|
|
128
|
+
{
|
|
129
|
+
name: 'variant',
|
|
130
|
+
description: 'How the language links render.',
|
|
131
|
+
component: Aglyn.FieldComponentType.SELECT,
|
|
132
|
+
label: 'Style',
|
|
133
|
+
// `text` is half of the declared `'text' | 'buttons'` union and the
|
|
134
|
+
// value the render already falls back to; as `''` the option was
|
|
135
|
+
// unpersistable (AGL-1191) and outside its own prop type (AGL-1451).
|
|
136
|
+
options: [
|
|
137
|
+
{
|
|
138
|
+
value: 'text',
|
|
139
|
+
label: 'Text (default)'
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
value: 'buttons',
|
|
143
|
+
label: 'Outlined buttons'
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'uppercase',
|
|
149
|
+
description: 'Show locale codes uppercased (EN, ES).',
|
|
150
|
+
component: Aglyn.FieldComponentType.CHECKBOX,
|
|
151
|
+
label: 'Uppercase'
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
};
|
|
155
|
+
export const presets = [
|
|
156
|
+
{
|
|
157
|
+
$id: generatePresetId(ID),
|
|
158
|
+
type: Aglyn.NodeType.PRESET,
|
|
159
|
+
displayName: 'Language Switcher',
|
|
160
|
+
pluginId: BUNDLE_ID,
|
|
161
|
+
description: 'Links between this screen’s translations',
|
|
162
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
163
|
+
icon: {
|
|
164
|
+
path: mdiTranslate.path,
|
|
165
|
+
sx: {
|
|
166
|
+
color: '#2196f3'
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
data: {
|
|
170
|
+
$id: null,
|
|
171
|
+
componentId: ID,
|
|
172
|
+
pluginId: BUNDLE_ID,
|
|
173
|
+
props: {}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
];
|
|
177
|
+
export default LanguageSwitcher;
|
|
178
|
+
|
|
179
|
+
//# sourceMappingURL=language-switcher.js.map
|