@aglyn/shared-ui-jsx-forms 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 +7 -0
- package/package.json +52 -0
- package/src/index.d.ts +17 -0
- package/src/index.js +18 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/color-picker-tokens.d.ts +135 -0
- package/src/lib/components/color-picker-tokens.js +431 -0
- package/src/lib/components/color-picker-tokens.js.map +1 -0
- package/src/lib/components/color-picker.component.d.ts +64 -0
- package/src/lib/components/color-picker.component.js +322 -0
- package/src/lib/components/color-picker.component.js.map +1 -0
- package/src/lib/components/create-artifact-drawer.component.d.ts +100 -0
- package/src/lib/components/create-artifact-drawer.component.js +184 -0
- package/src/lib/components/create-artifact-drawer.component.js.map +1 -0
- package/src/lib/components/grid-form-template.component.d.ts +21 -0
- package/src/lib/components/grid-form-template.component.js +81 -0
- package/src/lib/components/grid-form-template.component.js.map +1 -0
- package/src/lib/components/icon-select.component.d.ts +52 -0
- package/src/lib/components/icon-select.component.js +453 -0
- package/src/lib/components/icon-select.component.js.map +1 -0
- package/src/lib/components/select.component.d.ts +58 -0
- package/src/lib/components/select.component.js +107 -0
- package/src/lib/components/select.component.js.map +1 -0
- package/src/lib/components/switch.component.d.ts +38 -0
- package/src/lib/components/switch.component.js +76 -0
- package/src/lib/components/switch.component.js.map +1 -0
- package/src/lib/components/text-field.component.d.ts +45 -0
- package/src/lib/components/text-field.component.js +77 -0
- package/src/lib/components/text-field.component.js.map +1 -0
- package/src/lib/components/textarea.component.d.ts +45 -0
- package/src/lib/components/textarea.component.js +61 -0
- package/src/lib/components/textarea.component.js.map +1 -0
- package/src/lib/components/toggle-button.component.d.ts +27 -0
- package/src/lib/components/toggle-button.component.js +116 -0
- package/src/lib/components/toggle-button.component.js.map +1 -0
- package/src/lib/constants/component-mappers.d.ts +42 -0
- package/src/lib/constants/component-mappers.js +70 -0
- package/src/lib/constants/component-mappers.js.map +1 -0
- package/src/lib/constants/dynamic-fields.d.ts +45 -0
- package/src/lib/constants/dynamic-fields.js +65 -0
- package/src/lib/constants/dynamic-fields.js.map +1 -0
- package/src/lib/constants/field-configurations.d.ts +53 -0
- package/src/lib/constants/field-configurations.js +121 -0
- package/src/lib/constants/field-configurations.js.map +1 -0
- package/src/lib/constants/flags.d.ts +72 -0
- package/src/lib/constants/flags.js +69 -0
- package/src/lib/constants/flags.js.map +1 -0
- package/src/lib/hocs/with-grid-item.d.ts +25 -0
- package/src/lib/hocs/with-grid-item.js +48 -0
- package/src/lib/hocs/with-grid-item.js.map +1 -0
- package/src/lib/jsx-forms.d.ts +41 -0
- package/src/lib/jsx-forms.js +42 -0
- package/src/lib/jsx-forms.js.map +1 -0
- package/src/lib/mapper/breakpoint-span.d.ts +73 -0
- package/src/lib/mapper/breakpoint-span.js +346 -0
- package/src/lib/mapper/breakpoint-span.js.map +1 -0
- package/src/lib/mapper/checkbox.d.ts +43 -0
- package/src/lib/mapper/checkbox.js +111 -0
- package/src/lib/mapper/checkbox.js.map +1 -0
- package/src/lib/mapper/css-border.d.ts +113 -0
- package/src/lib/mapper/css-border.js +410 -0
- package/src/lib/mapper/css-border.js.map +1 -0
- package/src/lib/mapper/css-dimension.d.ts +89 -0
- package/src/lib/mapper/css-dimension.js +327 -0
- package/src/lib/mapper/css-dimension.js.map +1 -0
- package/src/lib/mapper/css-gradient.d.ts +110 -0
- package/src/lib/mapper/css-gradient.js +720 -0
- package/src/lib/mapper/css-gradient.js.map +1 -0
- package/src/lib/mapper/data-table.d.ts +23 -0
- package/src/lib/mapper/data-table.js +296 -0
- package/src/lib/mapper/data-table.js.map +1 -0
- package/src/lib/mapper/date-picker.d.ts +26 -0
- package/src/lib/mapper/date-picker.js +69 -0
- package/src/lib/mapper/date-picker.js.map +1 -0
- package/src/lib/mapper/dual-list-select.d.ts +115 -0
- package/src/lib/mapper/dual-list-select.js +353 -0
- package/src/lib/mapper/dual-list-select.js.map +1 -0
- package/src/lib/mapper/field-array.d.ts +71 -0
- package/src/lib/mapper/field-array.js +326 -0
- package/src/lib/mapper/field-array.js.map +1 -0
- package/src/lib/mapper/form-field-grid.d.ts +155 -0
- package/src/lib/mapper/form-field-grid.js +194 -0
- package/src/lib/mapper/form-field-grid.js.map +1 -0
- package/src/lib/mapper/index.d.ts +50 -0
- package/src/lib/mapper/index.js +49 -0
- package/src/lib/mapper/index.js.map +1 -0
- package/src/lib/mapper/multiple-choice-list.d.ts +32 -0
- package/src/lib/mapper/multiple-choice-list.js +105 -0
- package/src/lib/mapper/multiple-choice-list.js.map +1 -0
- package/src/lib/mapper/plain-text.d.ts +31 -0
- package/src/lib/mapper/plain-text.js +48 -0
- package/src/lib/mapper/plain-text.js.map +1 -0
- package/src/lib/mapper/preset-choice.d.ts +106 -0
- package/src/lib/mapper/preset-choice.js +267 -0
- package/src/lib/mapper/preset-choice.js.map +1 -0
- package/src/lib/mapper/radio.d.ts +40 -0
- package/src/lib/mapper/radio.js +122 -0
- package/src/lib/mapper/radio.js.map +1 -0
- package/src/lib/mapper/select.d.ts +60 -0
- package/src/lib/mapper/select.js +203 -0
- package/src/lib/mapper/select.js.map +1 -0
- package/src/lib/mapper/slider.d.ts +45 -0
- package/src/lib/mapper/slider.js +119 -0
- package/src/lib/mapper/slider.js.map +1 -0
- package/src/lib/mapper/stored-field-value.d.ts +23 -0
- package/src/lib/mapper/stored-field-value.js +29 -0
- package/src/lib/mapper/stored-field-value.js.map +1 -0
- package/src/lib/mapper/sub-form.d.ts +39 -0
- package/src/lib/mapper/sub-form.js +108 -0
- package/src/lib/mapper/sub-form.js.map +1 -0
- package/src/lib/mapper/switch.d.ts +47 -0
- package/src/lib/mapper/switch.js +93 -0
- package/src/lib/mapper/switch.js.map +1 -0
- package/src/lib/mapper/tabs.d.ts +34 -0
- package/src/lib/mapper/tabs.js +64 -0
- package/src/lib/mapper/tabs.js.map +1 -0
- package/src/lib/mapper/text-field.d.ts +33 -0
- package/src/lib/mapper/text-field.js +88 -0
- package/src/lib/mapper/text-field.js.map +1 -0
- package/src/lib/mapper/textarea.d.ts +31 -0
- package/src/lib/mapper/textarea.js +68 -0
- package/src/lib/mapper/textarea.js.map +1 -0
- package/src/lib/mapper/theme-scale.d.ts +79 -0
- package/src/lib/mapper/theme-scale.js +162 -0
- package/src/lib/mapper/theme-scale.js.map +1 -0
- package/src/lib/mapper/time-picker.d.ts +26 -0
- package/src/lib/mapper/time-picker.js +69 -0
- package/src/lib/mapper/time-picker.js.map +1 -0
- package/src/lib/mapper/types.d.ts +43 -0
- package/src/lib/mapper/types.js +22 -0
- package/src/lib/mapper/types.js.map +1 -0
- package/src/lib/mapper/validation-error.d.ts +24 -0
- package/src/lib/mapper/validation-error.js +24 -0
- package/src/lib/mapper/validation-error.js.map +1 -0
- package/src/lib/mapper/wizard.d.ts +21 -0
- package/src/lib/mapper/wizard.js +203 -0
- package/src/lib/mapper/wizard.js.map +1 -0
- package/src/lib/types.d.ts +19 -0
- package/src/lib/types.js +18 -0
- package/src/lib/types.js.map +1 -0
- package/src/lib/utils/option-is-equal-to-value.d.ts +20 -0
- package/src/lib/utils/option-is-equal-to-value.js +21 -0
- package/src/lib/utils/option-is-equal-to-value.js.map +1 -0
- package/src/lib/utils/validation-message.d.ts +22 -0
- package/src/lib/utils/validation-message.js +24 -0
- package/src/lib/utils/validation-message.js.map +1 -0
- package/src/lib/vendor/data-driven-forms.d.ts +33 -0
- package/src/lib/vendor/data-driven-forms.js +29 -0
- package/src/lib/vendor/data-driven-forms.js.map +1 -0
|
@@ -0,0 +1,720 @@
|
|
|
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, Fragment as _Fragment } 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 { ColorPicker as AglynColorPicker } from "@aglyn/shared-ui-color-picker";
|
|
20
|
+
import { buildCssGradient, parseCssGradient, parsePaletteTokenCssVar, paletteTokenToCssVar } from "@aglyn/shared-data-enums";
|
|
21
|
+
import { Box, Button, ButtonBase, ClickAwayListener, FormHelperText, IconButton, MenuItem, Paper, Popper, Stack, TextField as MuiTextField, Typography } from "@mui/material";
|
|
22
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
23
|
+
import { ColorTokenGrid, rgbColorToCss, TokenSwatch, useColorPickerTokenOptions } from "../components/color-picker-tokens.js";
|
|
24
|
+
import { useFieldApi } from "../vendor/data-driven-forms.js";
|
|
25
|
+
import FormFieldGrid, { buildFieldClear } from "./form-field-grid.js";
|
|
26
|
+
import { validationError } from "./validation-error.js";
|
|
27
|
+
/**
|
|
28
|
+
* CssGradient (AGL-1331): the Background Fill editor.
|
|
29
|
+
*
|
|
30
|
+
* The Styles panel's Colors group offered *Text Color* and *Background
|
|
31
|
+
* Color* and nothing else, so a gradient could not be authored at all —
|
|
32
|
+
* and typing one into Background Color was accepted, stored as
|
|
33
|
+
* `background-color: linear-gradient(…)`, and dropped by the CSS parser
|
|
34
|
+
* with no error anywhere. This is the control that expresses the value,
|
|
35
|
+
* and `describeCssColorProblem` is the guard that stops the silent store;
|
|
36
|
+
* the two ship together on purpose.
|
|
37
|
+
*
|
|
38
|
+
* The PERSISTED value is ONE CSS string under `backgroundImage` — the same
|
|
39
|
+
* contract as `CssDimensionField`, so nothing downstream has to know
|
|
40
|
+
* this editor exists. A **Solid** fill writes the explicit keyword
|
|
41
|
+
* `none`, which paints no image and leaves the neighbouring Background
|
|
42
|
+
* Color field to do the job; the two never fight over one property.
|
|
43
|
+
* **Default** writes `''`, which clears the property entirely.
|
|
44
|
+
*
|
|
45
|
+
* Solid and Default are two states, not one (AGL-1338). Solid shipped as
|
|
46
|
+
* "write nothing" — and on a reusable-component INSTANCE, where the panel
|
|
47
|
+
* edits an override slice, writing nothing IS "no override": the field
|
|
48
|
+
* could not be used to take a gradient off one placement, because the
|
|
49
|
+
* absence it produced was indistinguishable from never having touched it.
|
|
50
|
+
* `none` is a value, so it merges over the component's gradient and wins.
|
|
51
|
+
*
|
|
52
|
+
* Stops bind to palette TOKENS or to literals, and a single gradient can
|
|
53
|
+
* mix them: the marketing CTA's endpoints are `primary.main` /
|
|
54
|
+
* `secondary.main` while its mid stop `#7A5CF0` has no token at all. A
|
|
55
|
+
* token stop persists as `var(--mui-palette-primary-main, #00B0FF)` and is
|
|
56
|
+
* substituted against the site theme by the node renderer
|
|
57
|
+
* (`resolvePaletteVarsSx`) — see that module for why the reference is not
|
|
58
|
+
* left to the browser.
|
|
59
|
+
*
|
|
60
|
+
* Anything the editor cannot model — `conic-gradient`, `to bottom right`,
|
|
61
|
+
* a comma-stacked image list — falls back to a free-text box holding the
|
|
62
|
+
* raw string, so no existing value is destroyed by an editor that cannot
|
|
63
|
+
* show it. The stacked case reaches that box only because `parseCssGradient`
|
|
64
|
+
* splits top-level layers first (AGL-1336); until it did, a tint over a
|
|
65
|
+
* photo opened in the STOP editor and the author's first edit deleted the
|
|
66
|
+
* photo.
|
|
67
|
+
*/ /**
|
|
68
|
+
* The CSS an explicit **Solid** fill persists — `background-image`'s own
|
|
69
|
+
* initial value, so it renders identically to no declaration at all while
|
|
70
|
+
* remaining a VALUE that can override an inherited one (AGL-1338).
|
|
71
|
+
*/ export const SOLID_FILL_VALUE = 'none';
|
|
72
|
+
const DEFAULT_ANGLE = 180;
|
|
73
|
+
/** No value at all — the property stays off the node. */ const emptyDraft = {
|
|
74
|
+
fill: '',
|
|
75
|
+
angle: '',
|
|
76
|
+
positionX: '',
|
|
77
|
+
positionY: '',
|
|
78
|
+
stops: []
|
|
79
|
+
};
|
|
80
|
+
/** An explicit `background-image: none`. */ const solidDraft = {
|
|
81
|
+
fill: 'solid',
|
|
82
|
+
angle: '',
|
|
83
|
+
positionX: '',
|
|
84
|
+
positionY: '',
|
|
85
|
+
stops: []
|
|
86
|
+
};
|
|
87
|
+
export const seedGradientDraft = (value)=>{
|
|
88
|
+
const text = typeof value === 'string' ? value.trim() : '';
|
|
89
|
+
if (!text) return emptyDraft;
|
|
90
|
+
// `none` is this control's own Solid value, not a background it cannot
|
|
91
|
+
// model: reading it as raw CSS would strand the author in the text box
|
|
92
|
+
// on a value the control itself wrote.
|
|
93
|
+
if (text.toLowerCase() === SOLID_FILL_VALUE) return solidDraft;
|
|
94
|
+
const parsed = parseCssGradient(text);
|
|
95
|
+
// A non-gradient background image (`url(…)`) is still someone's value.
|
|
96
|
+
if (!parsed) return _extends({}, emptyDraft, {
|
|
97
|
+
fill: 'linear',
|
|
98
|
+
raw: text
|
|
99
|
+
});
|
|
100
|
+
if (parsed.raw !== undefined) {
|
|
101
|
+
return {
|
|
102
|
+
fill: parsed.type,
|
|
103
|
+
angle: '',
|
|
104
|
+
positionX: '',
|
|
105
|
+
positionY: '',
|
|
106
|
+
stops: [],
|
|
107
|
+
raw: parsed.raw
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
fill: parsed.type,
|
|
112
|
+
angle: parsed.angle === undefined ? '' : `${parsed.angle}`,
|
|
113
|
+
positionX: parsed.position ? `${parsed.position.x}` : '',
|
|
114
|
+
positionY: parsed.position ? `${parsed.position.y}` : '',
|
|
115
|
+
stops: parsed.stops
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
export const serializeGradientDraft = (draft)=>{
|
|
119
|
+
if (draft.raw !== undefined) return draft.raw;
|
|
120
|
+
if (draft.fill === '') return '';
|
|
121
|
+
if (draft.fill === 'solid') return SOLID_FILL_VALUE;
|
|
122
|
+
const angle = draft.angle.trim();
|
|
123
|
+
// Both boxes or neither: `at 50%` alone is a different CSS value (it
|
|
124
|
+
// defaults Y to centre), and writing one while the author has only filled
|
|
125
|
+
// the other would move the glow the moment they tabbed out of the first.
|
|
126
|
+
const x = draft.positionX.trim();
|
|
127
|
+
const y = draft.positionY.trim();
|
|
128
|
+
const hasPosition = draft.fill === 'radial' && x !== '' && y !== '';
|
|
129
|
+
const gradient = {
|
|
130
|
+
type: draft.fill,
|
|
131
|
+
angle: angle === '' ? undefined : Number(angle),
|
|
132
|
+
position: hasPosition ? {
|
|
133
|
+
x: Number(x),
|
|
134
|
+
y: Number(y)
|
|
135
|
+
} : undefined,
|
|
136
|
+
stops: draft.stops
|
|
137
|
+
};
|
|
138
|
+
return buildCssGradient(gradient);
|
|
139
|
+
};
|
|
140
|
+
/** The two stops a fresh gradient starts from — brand ends when available. */ function defaultStops(options) {
|
|
141
|
+
var _start_light, _end_light;
|
|
142
|
+
const pick = (path)=>options.find((option)=>option.value === path);
|
|
143
|
+
const start = pick('primary.main');
|
|
144
|
+
const end = pick('secondary.main');
|
|
145
|
+
return [
|
|
146
|
+
{
|
|
147
|
+
color: start ? paletteTokenToCssVar(start.value, (_start_light = start.light) != null ? _start_light : start.dark) : '#ffffff',
|
|
148
|
+
position: 0
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
color: end ? paletteTokenToCssVar(end.value, (_end_light = end.light) != null ? _end_light : end.dark) : '#000000',
|
|
152
|
+
position: 100
|
|
153
|
+
}
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
/** The token a stop is bound to, or undefined when it is a literal. */ function stopToken(color, options) {
|
|
157
|
+
const ref = parsePaletteTokenCssVar(color);
|
|
158
|
+
if (!ref) return undefined;
|
|
159
|
+
return options.find((option)=>option.value === ref.path);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A preview-safe copy of the value: token references resolve to the SITE
|
|
163
|
+
* theme's colour rather than to whatever `--mui-palette-*` the surrounding
|
|
164
|
+
* app happens to define (the console defines its own).
|
|
165
|
+
*/ function previewGradient(draft, options) {
|
|
166
|
+
const resolved = _extends({}, draft, {
|
|
167
|
+
stops: draft.stops.map((stop)=>{
|
|
168
|
+
var _ref, _ref1, _ref2;
|
|
169
|
+
const ref = parsePaletteTokenCssVar(stop.color);
|
|
170
|
+
if (!ref) return stop;
|
|
171
|
+
const token = options.find((option)=>option.value === ref.path);
|
|
172
|
+
const color = (_ref = (_ref1 = (_ref2 = token == null ? void 0 : token.light) != null ? _ref2 : token == null ? void 0 : token.dark) != null ? _ref1 : ref.fallback) != null ? _ref : stop.color;
|
|
173
|
+
return _extends({}, stop, {
|
|
174
|
+
color
|
|
175
|
+
});
|
|
176
|
+
})
|
|
177
|
+
});
|
|
178
|
+
return serializeGradientDraft(resolved);
|
|
179
|
+
}
|
|
180
|
+
/** Swatch + label button that opens one stop's two-stage colour picker. */ const GradientStopColor = (props)=>{
|
|
181
|
+
var _ref, _ref1, _ref2, _ref3;
|
|
182
|
+
var _parsePaletteTokenCssVar;
|
|
183
|
+
const { color, label, disabled, presetColors, ColorPickerProps, onChange } = props;
|
|
184
|
+
const options = useColorPickerTokenOptions();
|
|
185
|
+
const token = stopToken(color, options);
|
|
186
|
+
const literal = (_ref = (_parsePaletteTokenCssVar = parsePaletteTokenCssVar(color)) == null ? void 0 : _parsePaletteTokenCssVar.fallback) != null ? _ref : color;
|
|
187
|
+
const [anchor, setAnchor] = useState(null);
|
|
188
|
+
const [stage, setStage] = useState('tokens');
|
|
189
|
+
const handleOpen = useCallback((event)=>{
|
|
190
|
+
// Tokens first, exactly like the colour field's two-stage picker —
|
|
191
|
+
// unless the theme offers none, in which case the token stage would
|
|
192
|
+
// be an empty grid.
|
|
193
|
+
setStage(options.length ? 'tokens' : 'custom');
|
|
194
|
+
setAnchor((previous)=>previous ? null : event.currentTarget);
|
|
195
|
+
}, [
|
|
196
|
+
options.length
|
|
197
|
+
]);
|
|
198
|
+
return /*#__PURE__*/ _jsx(ClickAwayListener, {
|
|
199
|
+
onClickAway: ()=>setAnchor(null),
|
|
200
|
+
children: /*#__PURE__*/ _jsxs(Box, {
|
|
201
|
+
sx: {
|
|
202
|
+
flexGrow: 1,
|
|
203
|
+
minWidth: 0
|
|
204
|
+
},
|
|
205
|
+
children: [
|
|
206
|
+
/*#__PURE__*/ _jsxs(ButtonBase, {
|
|
207
|
+
"aria-label": label,
|
|
208
|
+
disabled: disabled,
|
|
209
|
+
onClick: handleOpen,
|
|
210
|
+
sx: {
|
|
211
|
+
width: '100%',
|
|
212
|
+
justifyContent: 'flex-start',
|
|
213
|
+
gap: 0.75,
|
|
214
|
+
px: 1,
|
|
215
|
+
py: 0.75,
|
|
216
|
+
border: 1,
|
|
217
|
+
borderColor: 'divider',
|
|
218
|
+
borderRadius: 1
|
|
219
|
+
},
|
|
220
|
+
children: [
|
|
221
|
+
token ? /*#__PURE__*/ _jsx(TokenSwatch, {
|
|
222
|
+
light: token.light,
|
|
223
|
+
dark: token.dark,
|
|
224
|
+
size: 18
|
|
225
|
+
}) : /*#__PURE__*/ _jsx(Box, {
|
|
226
|
+
sx: {
|
|
227
|
+
width: 18,
|
|
228
|
+
height: 18,
|
|
229
|
+
flexShrink: 0,
|
|
230
|
+
borderRadius: '50%',
|
|
231
|
+
border: 1,
|
|
232
|
+
borderColor: 'divider',
|
|
233
|
+
backgroundColor: literal
|
|
234
|
+
}
|
|
235
|
+
}),
|
|
236
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
237
|
+
variant: "caption",
|
|
238
|
+
noWrap: true,
|
|
239
|
+
children: token ? token.label : literal
|
|
240
|
+
})
|
|
241
|
+
]
|
|
242
|
+
}),
|
|
243
|
+
/*#__PURE__*/ _jsx(Popper, {
|
|
244
|
+
open: Boolean(anchor),
|
|
245
|
+
anchorEl: anchor,
|
|
246
|
+
sx: {
|
|
247
|
+
zIndex: 'tooltip',
|
|
248
|
+
maxWidth: 280
|
|
249
|
+
},
|
|
250
|
+
disablePortal: true,
|
|
251
|
+
children: stage === 'tokens' && options.length ? /*#__PURE__*/ _jsx(ColorTokenGrid, {
|
|
252
|
+
options: options,
|
|
253
|
+
value: (_ref1 = token == null ? void 0 : token.value) != null ? _ref1 : '',
|
|
254
|
+
onSelect: (path)=>{
|
|
255
|
+
var _ref;
|
|
256
|
+
const picked = options.find((option)=>option.value === path);
|
|
257
|
+
onChange(paletteTokenToCssVar(path, (_ref = picked == null ? void 0 : picked.light) != null ? _ref : picked == null ? void 0 : picked.dark));
|
|
258
|
+
setAnchor(null);
|
|
259
|
+
},
|
|
260
|
+
onCustom: ()=>setStage('custom')
|
|
261
|
+
}) : /*#__PURE__*/ _jsxs(Paper, {
|
|
262
|
+
sx: {
|
|
263
|
+
p: 0.5
|
|
264
|
+
},
|
|
265
|
+
children: [
|
|
266
|
+
options.length ? /*#__PURE__*/ _jsx(Button, {
|
|
267
|
+
size: "small",
|
|
268
|
+
fullWidth: true,
|
|
269
|
+
sx: {
|
|
270
|
+
mb: 0.5
|
|
271
|
+
},
|
|
272
|
+
onClick: ()=>setStage('tokens'),
|
|
273
|
+
children: '‹ Theme colors'
|
|
274
|
+
}) : null,
|
|
275
|
+
/*#__PURE__*/ _jsx(AglynColorPicker, _extends({}, ColorPickerProps, {
|
|
276
|
+
// A `var()` reference is not parseable by the picker; seed
|
|
277
|
+
// it with the colour that reference resolves to.
|
|
278
|
+
color: (_ref2 = (_ref3 = token == null ? void 0 : token.light) != null ? _ref3 : token == null ? void 0 : token.dark) != null ? _ref2 : literal,
|
|
279
|
+
onChange: (picked)=>onChange(rgbColorToCss(picked.rgb)),
|
|
280
|
+
presetColors: presetColors
|
|
281
|
+
}))
|
|
282
|
+
]
|
|
283
|
+
})
|
|
284
|
+
})
|
|
285
|
+
]
|
|
286
|
+
})
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
GradientStopColor.displayName = 'AglynGradientStopColor';
|
|
290
|
+
export const CssGradientField = (props)=>{
|
|
291
|
+
const _useFieldApi = useFieldApi(props), { input, isReadOnly, isDisabled, label, helperText, description, validateOnMount, meta, help, presetColors, unsetLabel = 'Default', clearable, ColorPickerProps, FormFieldGridProps = {}, // Free-text leftovers from an attribute schema that must never reach
|
|
292
|
+
// the DOM.
|
|
293
|
+
inputProps: _inputProps, InputProps: _InputProps, multiline: _multiline, placeholder: _placeholder } = _useFieldApi, rest = _object_without_properties_loose(_useFieldApi, [
|
|
294
|
+
"input",
|
|
295
|
+
"isReadOnly",
|
|
296
|
+
"isDisabled",
|
|
297
|
+
"label",
|
|
298
|
+
"helperText",
|
|
299
|
+
"description",
|
|
300
|
+
"validateOnMount",
|
|
301
|
+
"meta",
|
|
302
|
+
"help",
|
|
303
|
+
"presetColors",
|
|
304
|
+
"unsetLabel",
|
|
305
|
+
"clearable",
|
|
306
|
+
"ColorPickerProps",
|
|
307
|
+
"FormFieldGridProps",
|
|
308
|
+
"inputProps",
|
|
309
|
+
"InputProps",
|
|
310
|
+
"multiline",
|
|
311
|
+
"placeholder"
|
|
312
|
+
]);
|
|
313
|
+
const invalid = validationError(meta, validateOnMount);
|
|
314
|
+
const options = useColorPickerTokenOptions();
|
|
315
|
+
const value = typeof input.value === 'string' ? input.value : '';
|
|
316
|
+
const locked = Boolean(isDisabled || isReadOnly);
|
|
317
|
+
const [draft, setDraft] = useState(()=>seedGradientDraft(value));
|
|
318
|
+
// Re-seed only when the value changed OUTSIDE this field (a different
|
|
319
|
+
// node selected, an undo) — re-seeding from our own emits would fight
|
|
320
|
+
// the caret in the angle and position boxes.
|
|
321
|
+
const emittedRef = useRef(value);
|
|
322
|
+
useEffect(()=>{
|
|
323
|
+
if (value === emittedRef.current) return;
|
|
324
|
+
emittedRef.current = value;
|
|
325
|
+
setDraft(seedGradientDraft(value));
|
|
326
|
+
}, [
|
|
327
|
+
value
|
|
328
|
+
]);
|
|
329
|
+
const commit = useCallback((next)=>{
|
|
330
|
+
const serialized = serializeGradientDraft(next);
|
|
331
|
+
emittedRef.current = serialized;
|
|
332
|
+
setDraft(next);
|
|
333
|
+
input.onChange(serialized);
|
|
334
|
+
}, [
|
|
335
|
+
input
|
|
336
|
+
]);
|
|
337
|
+
const handleFillChange = useCallback((event)=>{
|
|
338
|
+
var _event_target_value;
|
|
339
|
+
const fill = (_event_target_value = event.target.value) != null ? _event_target_value : '';
|
|
340
|
+
// Neither non-gradient choice keeps stops, but they persist
|
|
341
|
+
// differently: Solid writes `none`, Default writes nothing.
|
|
342
|
+
if (fill === '' || fill === 'solid') {
|
|
343
|
+
commit(_extends({}, emptyDraft, {
|
|
344
|
+
fill
|
|
345
|
+
}));
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
// Switching INTO a gradient with nothing to show yet starts from the
|
|
349
|
+
// brand ends, so the author sees a gradient immediately instead of an
|
|
350
|
+
// empty stop list that serializes to nothing.
|
|
351
|
+
const stops = draft.stops.length >= 2 ? draft.stops : defaultStops(options);
|
|
352
|
+
const angle = fill === 'linear' ? draft.angle || `${DEFAULT_ANGLE}` : '';
|
|
353
|
+
// Position belongs to radial; carried across a radial→radial change
|
|
354
|
+
// (Solid and back) and dropped when the fill is no longer radial, so a
|
|
355
|
+
// linear gradient cannot persist a centre no CSS would use.
|
|
356
|
+
const positionX = fill === 'radial' ? draft.positionX : '';
|
|
357
|
+
const positionY = fill === 'radial' ? draft.positionY : '';
|
|
358
|
+
commit({
|
|
359
|
+
fill,
|
|
360
|
+
angle,
|
|
361
|
+
positionX,
|
|
362
|
+
positionY,
|
|
363
|
+
stops,
|
|
364
|
+
raw: undefined
|
|
365
|
+
});
|
|
366
|
+
}, [
|
|
367
|
+
commit,
|
|
368
|
+
draft.angle,
|
|
369
|
+
draft.positionX,
|
|
370
|
+
draft.positionY,
|
|
371
|
+
draft.stops,
|
|
372
|
+
options
|
|
373
|
+
]);
|
|
374
|
+
const handlePositionChange = useCallback((axis)=>(event)=>{
|
|
375
|
+
commit(_extends({}, draft, {
|
|
376
|
+
[axis]: event.target.value
|
|
377
|
+
}));
|
|
378
|
+
}, [
|
|
379
|
+
commit,
|
|
380
|
+
draft
|
|
381
|
+
]);
|
|
382
|
+
const handleAngleChange = useCallback((event)=>{
|
|
383
|
+
commit(_extends({}, draft, {
|
|
384
|
+
angle: event.target.value
|
|
385
|
+
}));
|
|
386
|
+
}, [
|
|
387
|
+
commit,
|
|
388
|
+
draft
|
|
389
|
+
]);
|
|
390
|
+
const handleStopColor = useCallback((index)=>(color)=>{
|
|
391
|
+
const stops = draft.stops.map((stop, i)=>i === index ? _extends({}, stop, {
|
|
392
|
+
color
|
|
393
|
+
}) : stop);
|
|
394
|
+
commit(_extends({}, draft, {
|
|
395
|
+
stops
|
|
396
|
+
}));
|
|
397
|
+
}, [
|
|
398
|
+
commit,
|
|
399
|
+
draft
|
|
400
|
+
]);
|
|
401
|
+
const handleStopPosition = useCallback((index)=>(event)=>{
|
|
402
|
+
const text = event.target.value.trim();
|
|
403
|
+
const position = text === '' ? undefined : Number(text);
|
|
404
|
+
const stops = draft.stops.map((stop, i)=>i === index ? _extends({}, stop, {
|
|
405
|
+
position
|
|
406
|
+
}) : stop);
|
|
407
|
+
commit(_extends({}, draft, {
|
|
408
|
+
stops
|
|
409
|
+
}));
|
|
410
|
+
}, [
|
|
411
|
+
commit,
|
|
412
|
+
draft
|
|
413
|
+
]);
|
|
414
|
+
const handleAddStop = useCallback(()=>{
|
|
415
|
+
var _ref;
|
|
416
|
+
const last = draft.stops[draft.stops.length - 1];
|
|
417
|
+
const previous = draft.stops[draft.stops.length - 2];
|
|
418
|
+
const between = typeof (last == null ? void 0 : last.position) === 'number' && typeof (previous == null ? void 0 : previous.position) === 'number' ? Math.round((last.position + previous.position) / 2) : undefined;
|
|
419
|
+
const stop = {
|
|
420
|
+
color: (_ref = last == null ? void 0 : last.color) != null ? _ref : '#ffffff',
|
|
421
|
+
position: between
|
|
422
|
+
};
|
|
423
|
+
// The new stop lands BEFORE the last one when it can be positioned
|
|
424
|
+
// between the two — the CTA's mid stop is that shape.
|
|
425
|
+
const stops = between === undefined ? [
|
|
426
|
+
...draft.stops,
|
|
427
|
+
stop
|
|
428
|
+
] : [
|
|
429
|
+
...draft.stops.slice(0, -1),
|
|
430
|
+
stop,
|
|
431
|
+
last
|
|
432
|
+
];
|
|
433
|
+
commit(_extends({}, draft, {
|
|
434
|
+
stops
|
|
435
|
+
}));
|
|
436
|
+
}, [
|
|
437
|
+
commit,
|
|
438
|
+
draft
|
|
439
|
+
]);
|
|
440
|
+
const handleRemoveStop = useCallback((index)=>()=>{
|
|
441
|
+
commit(_extends({}, draft, {
|
|
442
|
+
stops: draft.stops.filter((_, i)=>i !== index)
|
|
443
|
+
}));
|
|
444
|
+
}, [
|
|
445
|
+
commit,
|
|
446
|
+
draft
|
|
447
|
+
]);
|
|
448
|
+
const handleRawChange = useCallback((event)=>{
|
|
449
|
+
const text = event.target.value;
|
|
450
|
+
// Edited back into a gradient this editor CAN model? Take the
|
|
451
|
+
// structured controls back rather than stranding the author in the
|
|
452
|
+
// text box (the css-dimension rule).
|
|
453
|
+
const reseeded = seedGradientDraft(text);
|
|
454
|
+
commit(reseeded.raw === undefined && text.trim() !== '' ? reseeded : _extends({}, draft, {
|
|
455
|
+
raw: text
|
|
456
|
+
}));
|
|
457
|
+
}, [
|
|
458
|
+
commit,
|
|
459
|
+
draft
|
|
460
|
+
]);
|
|
461
|
+
const preview = useMemo(()=>previewGradient(draft, options), [
|
|
462
|
+
draft,
|
|
463
|
+
options
|
|
464
|
+
]);
|
|
465
|
+
// Back to unset in one click (AGL-2486) — including out of the raw-CSS
|
|
466
|
+
// fallback, which the fill-type select cannot leave on its own because it
|
|
467
|
+
// is disabled while a raw value is held.
|
|
468
|
+
const clear = buildFieldClear({
|
|
469
|
+
clearable,
|
|
470
|
+
label,
|
|
471
|
+
hasValue: value !== '',
|
|
472
|
+
locked,
|
|
473
|
+
onClear: ()=>commit(_extends({}, emptyDraft, {
|
|
474
|
+
raw: undefined
|
|
475
|
+
}))
|
|
476
|
+
});
|
|
477
|
+
return /*#__PURE__*/ _jsxs(FormFieldGrid, _extends({
|
|
478
|
+
help: help,
|
|
479
|
+
clear: clear
|
|
480
|
+
}, FormFieldGridProps, {
|
|
481
|
+
children: [
|
|
482
|
+
/*#__PURE__*/ _jsxs(MuiTextField, _extends({}, rest, {
|
|
483
|
+
select: true,
|
|
484
|
+
fullWidth: true,
|
|
485
|
+
size: "small",
|
|
486
|
+
name: input.name,
|
|
487
|
+
label: label,
|
|
488
|
+
value: draft.raw !== undefined ? 'custom' : draft.fill,
|
|
489
|
+
onChange: handleFillChange,
|
|
490
|
+
disabled: locked || draft.raw !== undefined,
|
|
491
|
+
error: !!invalid,
|
|
492
|
+
helperText: invalid || (meta.touched || validateOnMount) && meta.warning || helperText || description,
|
|
493
|
+
slotProps: {
|
|
494
|
+
htmlInput: {
|
|
495
|
+
'aria-label': 'Fill type'
|
|
496
|
+
},
|
|
497
|
+
// Without displayEmpty a MUI Select renders NOTHING for `''`,
|
|
498
|
+
// which would show the unset state as a broken control.
|
|
499
|
+
select: {
|
|
500
|
+
displayEmpty: true
|
|
501
|
+
},
|
|
502
|
+
// …and `displayEmpty` alone prints the label ON TOP of the option
|
|
503
|
+
// it just drew (AGL-2486). MUI shrinks a label when the input
|
|
504
|
+
// reports itself FILLED, and an empty Select reports the
|
|
505
|
+
// opposite no matter what it is rendering — so the unset choice
|
|
506
|
+
// and the field name landed in the same few pixels and neither
|
|
507
|
+
// could be read. A rendered option is content; say so.
|
|
508
|
+
inputLabel: {
|
|
509
|
+
shrink: true
|
|
510
|
+
}
|
|
511
|
+
},
|
|
512
|
+
children: [
|
|
513
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
514
|
+
value: "",
|
|
515
|
+
children: unsetLabel
|
|
516
|
+
}),
|
|
517
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
518
|
+
value: "solid",
|
|
519
|
+
children: "Solid color"
|
|
520
|
+
}),
|
|
521
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
522
|
+
value: "linear",
|
|
523
|
+
children: "Linear gradient"
|
|
524
|
+
}),
|
|
525
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
526
|
+
value: "radial",
|
|
527
|
+
children: "Radial gradient"
|
|
528
|
+
}),
|
|
529
|
+
draft.raw !== undefined ? /*#__PURE__*/ _jsx(MenuItem, {
|
|
530
|
+
value: "custom",
|
|
531
|
+
children: "Custom CSS"
|
|
532
|
+
}) : null
|
|
533
|
+
]
|
|
534
|
+
})),
|
|
535
|
+
draft.raw !== undefined ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
536
|
+
children: [
|
|
537
|
+
/*#__PURE__*/ _jsx(MuiTextField, {
|
|
538
|
+
fullWidth: true,
|
|
539
|
+
size: "small",
|
|
540
|
+
multiline: true,
|
|
541
|
+
label: "Background image",
|
|
542
|
+
value: draft.raw,
|
|
543
|
+
onChange: handleRawChange,
|
|
544
|
+
disabled: locked,
|
|
545
|
+
sx: {
|
|
546
|
+
mt: 1
|
|
547
|
+
},
|
|
548
|
+
slotProps: {
|
|
549
|
+
htmlInput: {
|
|
550
|
+
'aria-label': 'Background image CSS'
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}),
|
|
554
|
+
/*#__PURE__*/ _jsx(FormHelperText, {
|
|
555
|
+
children: 'This background is richer than the stop editor can show — ' + 'stacked layers, a conic gradient, a direction keyword. It is ' + 'kept exactly as written; editing it back to a plain linear ' + 'or radial gradient brings the controls back.'
|
|
556
|
+
})
|
|
557
|
+
]
|
|
558
|
+
}) : draft.fill !== 'linear' && draft.fill !== 'radial' ? null : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
559
|
+
children: [
|
|
560
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
561
|
+
"aria-label": "Gradient preview",
|
|
562
|
+
sx: {
|
|
563
|
+
mt: 1,
|
|
564
|
+
height: 28,
|
|
565
|
+
borderRadius: 1,
|
|
566
|
+
border: 1,
|
|
567
|
+
borderColor: 'divider',
|
|
568
|
+
backgroundImage: preview || 'none'
|
|
569
|
+
}
|
|
570
|
+
}),
|
|
571
|
+
draft.fill === 'linear' ? /*#__PURE__*/ _jsx(MuiTextField, {
|
|
572
|
+
fullWidth: true,
|
|
573
|
+
size: "small",
|
|
574
|
+
type: "number",
|
|
575
|
+
label: "Angle",
|
|
576
|
+
value: draft.angle,
|
|
577
|
+
onChange: handleAngleChange,
|
|
578
|
+
disabled: locked,
|
|
579
|
+
sx: {
|
|
580
|
+
mt: 1
|
|
581
|
+
},
|
|
582
|
+
slotProps: {
|
|
583
|
+
htmlInput: {
|
|
584
|
+
'aria-label': 'Angle',
|
|
585
|
+
inputMode: 'numeric'
|
|
586
|
+
},
|
|
587
|
+
input: {
|
|
588
|
+
endAdornment: /*#__PURE__*/ _jsx(Typography, {
|
|
589
|
+
variant: "caption",
|
|
590
|
+
children: "deg"
|
|
591
|
+
})
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}) : null,
|
|
595
|
+
draft.fill === 'radial' ? /*#__PURE__*/ _jsxs(Stack, {
|
|
596
|
+
direction: "row",
|
|
597
|
+
spacing: 0.5,
|
|
598
|
+
sx: {
|
|
599
|
+
mt: 1
|
|
600
|
+
},
|
|
601
|
+
children: [
|
|
602
|
+
/*#__PURE__*/ _jsx(MuiTextField, {
|
|
603
|
+
fullWidth: true,
|
|
604
|
+
size: "small",
|
|
605
|
+
type: "number",
|
|
606
|
+
label: "Center X",
|
|
607
|
+
value: draft.positionX,
|
|
608
|
+
onChange: handlePositionChange('positionX'),
|
|
609
|
+
disabled: locked,
|
|
610
|
+
slotProps: {
|
|
611
|
+
htmlInput: {
|
|
612
|
+
'aria-label': 'Center X',
|
|
613
|
+
inputMode: 'numeric'
|
|
614
|
+
},
|
|
615
|
+
input: {
|
|
616
|
+
endAdornment: /*#__PURE__*/ _jsx(Typography, {
|
|
617
|
+
variant: "caption",
|
|
618
|
+
children: '%'
|
|
619
|
+
})
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}),
|
|
623
|
+
/*#__PURE__*/ _jsx(MuiTextField, {
|
|
624
|
+
fullWidth: true,
|
|
625
|
+
size: "small",
|
|
626
|
+
type: "number",
|
|
627
|
+
label: "Center Y",
|
|
628
|
+
value: draft.positionY,
|
|
629
|
+
onChange: handlePositionChange('positionY'),
|
|
630
|
+
disabled: locked,
|
|
631
|
+
slotProps: {
|
|
632
|
+
htmlInput: {
|
|
633
|
+
'aria-label': 'Center Y',
|
|
634
|
+
inputMode: 'numeric'
|
|
635
|
+
},
|
|
636
|
+
input: {
|
|
637
|
+
endAdornment: /*#__PURE__*/ _jsx(Typography, {
|
|
638
|
+
variant: "caption",
|
|
639
|
+
children: '%'
|
|
640
|
+
})
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
})
|
|
644
|
+
]
|
|
645
|
+
}) : null,
|
|
646
|
+
/*#__PURE__*/ _jsx(Stack, {
|
|
647
|
+
spacing: 0.5,
|
|
648
|
+
sx: {
|
|
649
|
+
mt: 1
|
|
650
|
+
},
|
|
651
|
+
children: draft.stops.map((stop, index)=>{
|
|
652
|
+
var _stop_position;
|
|
653
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
654
|
+
direction: "row",
|
|
655
|
+
spacing: 0.5,
|
|
656
|
+
sx: {
|
|
657
|
+
alignItems: 'center'
|
|
658
|
+
},
|
|
659
|
+
children: [
|
|
660
|
+
/*#__PURE__*/ _jsx(GradientStopColor, {
|
|
661
|
+
color: stop.color,
|
|
662
|
+
label: `Stop ${index + 1} color`,
|
|
663
|
+
disabled: locked,
|
|
664
|
+
presetColors: presetColors,
|
|
665
|
+
ColorPickerProps: ColorPickerProps,
|
|
666
|
+
onChange: handleStopColor(index)
|
|
667
|
+
}),
|
|
668
|
+
/*#__PURE__*/ _jsx(MuiTextField, {
|
|
669
|
+
size: "small",
|
|
670
|
+
type: "number",
|
|
671
|
+
value: (_stop_position = stop.position) != null ? _stop_position : '',
|
|
672
|
+
onChange: handleStopPosition(index),
|
|
673
|
+
disabled: locked,
|
|
674
|
+
sx: {
|
|
675
|
+
width: 88
|
|
676
|
+
},
|
|
677
|
+
slotProps: {
|
|
678
|
+
htmlInput: {
|
|
679
|
+
'aria-label': `Stop ${index + 1} position`,
|
|
680
|
+
inputMode: 'numeric'
|
|
681
|
+
},
|
|
682
|
+
input: {
|
|
683
|
+
endAdornment: /*#__PURE__*/ _jsx(Typography, {
|
|
684
|
+
variant: "caption",
|
|
685
|
+
children: "%"
|
|
686
|
+
})
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}),
|
|
690
|
+
/*#__PURE__*/ _jsx(IconButton, {
|
|
691
|
+
size: "small",
|
|
692
|
+
"aria-label": `Remove stop ${index + 1}`,
|
|
693
|
+
// A gradient needs two ends; the last two are not
|
|
694
|
+
// removable, so the control can never serialize to a
|
|
695
|
+
// value that silently clears the background.
|
|
696
|
+
disabled: locked || draft.stops.length <= 2,
|
|
697
|
+
onClick: handleRemoveStop(index),
|
|
698
|
+
children: '×'
|
|
699
|
+
})
|
|
700
|
+
]
|
|
701
|
+
}, index);
|
|
702
|
+
})
|
|
703
|
+
}),
|
|
704
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
705
|
+
size: "small",
|
|
706
|
+
onClick: handleAddStop,
|
|
707
|
+
disabled: locked,
|
|
708
|
+
sx: {
|
|
709
|
+
mt: 0.5
|
|
710
|
+
},
|
|
711
|
+
children: "Add stop"
|
|
712
|
+
})
|
|
713
|
+
]
|
|
714
|
+
})
|
|
715
|
+
]
|
|
716
|
+
}));
|
|
717
|
+
};
|
|
718
|
+
export default CssGradientField;
|
|
719
|
+
|
|
720
|
+
//# sourceMappingURL=css-gradient.js.map
|