PageSourceSearch

https://id.priyadi.net/assets/controllers/theme-editor_controller-q6BJp40.js

js priyadi.net collected 2026-09-24 19:58:49 UTC 20,557 bytes, 440 lines download raw bytes

1function _array_like_to_array(arr, len) {
2    if (len == null || len > arr.length) len = arr.length;
3    for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4    return arr2;
5}
6function _array_with_holes(arr) {
7    if (Array.isArray(arr)) return arr;
8}
9function _assert_this_initialized(self) {
10    if (self === void 0) {
11        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
12    }
13    return self;
14}
15function _class_call_check(instance, Constructor) {
16    if (!(instance instanceof Constructor)) {
17        throw new TypeError("Cannot call a class as a function");
18    }
19}
20function _defineProperties(target, props) {
21    for(var i = 0; i < props.length; i++){
22        var descriptor = props[i];
23        descriptor.enumerable = descriptor.enumerable || false;
24        descriptor.configurable = true;
25        if ("value" in descriptor) descriptor.writable = true;
26        Object.defineProperty(target, descriptor.key, descriptor);
27    }
28}
29function _create_class(Constructor, protoProps, staticProps) {
30    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
31    if (staticProps) _defineProperties(Constructor, staticProps);
32    return Constructor;
33}
34function _define_property(obj, key, value) {
35    if (key in obj) {
36        Object.defineProperty(obj, key, {
37            value: value,
38            enumerable: true,
39            configurable: true,
40            writable: true
41        });
42    } else {
43        obj[key] = value;
44    }
45    return obj;
46}
47function _get_prototype_of(o) {
48    _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
49        return o.__proto__ || Object.getPrototypeOf(o);
50    };
51    return _get_prototype_of(o);
52}
53function _inherits(subClass, superClass) {
54    if (typeof superClass !== "function" && superClass !== null) {
55        throw new TypeError("Super expression must either be null or a function");
56    }
57    subClass.prototype = Object.create(superClass && superClass.prototype, {
58        constructor: {
59            value: subClass,
60            writable: true,
61            configurable: true
62        }
63    });
64    if (superClass) _set_prototype_of(subClass, superClass);
65}
66function _iterable_to_array_limit(arr, i) {
67    var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
68    if (_i == null) return;
69    var _arr = [];
70    var _n = true;
71    var _d = false;
72    var _s, _e;
73    try {
74        for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
75            _arr.push(_s.value);
76            if (i && _arr.length === i) break;
77        }
78    } catch (err) {
79        _d = true;
80        _e = err;
81    } finally{
82        try {
83            if (!_n && _i["return"] != null) _i["return"]();
84        } finally{
85            if (_d) throw _e;
86        }
87    }
88    return _arr;
89}
90function _non_iterable_rest() {
91    throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
92}
93function _object_spread(target) {
94    for(var i = 1; i < arguments.length; i++){
95        var source = arguments[i] != null ? arguments[i] : {};
96        var ownKeys = Object.keys(source);
97        if (typeof Object.getOwnPropertySymbols === "function") {
98            ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
99                return Object.getOwnPropertyDescriptor(source, sym).enumerable;
100            }));
101        }
102        ownKeys.forEach(function(key) {
103            _define_property(target, key, source[key]);
104        });
105    }
106    return target;
107}
108function _possible_constructor_return(self, call) {
109    if (call && (_type_of(call) === "object" || typeof call === "function")) {
110        return call;
111    }
112    return _assert_this_initialized(self);
113}
114function _set_prototype_of(o, p) {
115    _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) {
116        o.__proto__ = p;
117        return o;
118    };
119    return _set_prototype_of(o, p);
120}
121function _sliced_to_array(arr, i) {
122    return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
123}
124function _type_of(obj) {
125    "@swc/helpers - typeof";
126    return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
127}
128function _unsupported_iterable_to_array(o, minLen) {
129    if (!o) return;
130    if (typeof o === "string") return _array_like_to_array(o, minLen);
131    var n = Object.prototype.toString.call(o).slice(8, -1);
132    if (n === "Object" && o.constructor) n = o.constructor.name;
133    if (n === "Map" || n === "Set") return Array.from(n);
134    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
135}
136function _is_native_reflect_construct() {
137    if (typeof Reflect === "undefined" || !Reflect.construct) return false;
138    if (Reflect.construct.sham) return false;
139    if (typeof Proxy === "function") return true;
140    try {
141        Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
142        return true;
143    } catch (e) {
144        return false;
145    }
146}
147function _create_super(Derived) {
148    var hasNativeReflectConstruct = _is_native_reflect_construct();
149    return function _createSuperInternal() {
150        var Super = _get_prototype_of(Derived), result;
151        if (hasNativeReflectConstruct) {
152            var NewTarget = _get_prototype_of(this).constructor;
153            result = Reflect.construct(Super, arguments, NewTarget);
154        } else {
155            result = Super.apply(this, arguments);
156        }
157        return _possible_constructor_return(this, result);
158    };
159}
160import { Controller } from "@hotwired/stimulus";
161import { accentRamp, surfaceRamp, terminalRamp, STOCK_BACKGROUND } from "../lib/theme-ramp.js";
162var _class = /*#__PURE__*/ function(Controller) {
163    "use strict";
164    _inherits(_class, Controller);
165    var _super = _create_super(_class);
166    function _class() {
167        _class_call_check(this, _class);
168        var _this;
169        _this = _super.apply(this, arguments);
170        _define_property(_assert_this_initialized(_this), "appliedVars", new Set());
171        _define_property(_assert_this_initialized(_this), "onFrameLoad", function() {
172            // A (re)loaded iframe starts from the server-rendered theme; the
173            // inline vars we wrote on its previous document are gone.
174            _this.appliedVars.clear();
175            _this.preview();
176        });
177        return _this;
178    }
179    _create_class(_class, [
180        {
181            key: "connect",
182            value: function connect() {
183                var _this_frame;
184                // Sections only — no preview yet: the server-rendered theme is
185                // already live, and the heuristic preview would visibly shift it.
186                this.syncSections();
187                (_this_frame = this.frame()) === null || _this_frame === void 0 ? void 0 : _this_frame.addEventListener("load", this.onFrameLoad);
188            }
189        },
190        {
191            key: "disconnect",
192            value: function disconnect() {
193                var _this_frame;
194                this.clearPreview();
195                (_this_frame = this.frame()) === null || _this_frame === void 0 ? void 0 : _this_frame.removeEventListener("load", this.onFrameLoad);
196            }
197        },
198        {
199            key: "refresh",
200            value: function refresh() {
201                this.syncSections();
202                this.preview();
203            }
204        },
205        {
206            key: "frame",
207            value: function frame() {
208                if (!this.frameValue) {
209                    return null;
210                }
211                return document.querySelector(this.frameValue);
212            }
213        },
214        {
215            key: "previewRoot",
216            value: /**
217     * The <html> the preview vars go on: the preview iframe's when
218     * configured (and reachable — it is same-origin, but may not have
219     * loaded yet), this page's otherwise.
220     */ function previewRoot() {
221                var _this_frame_contentDocument, _this_frame;
222                if (!this.frameValue) {
223                    return document.documentElement;
224                }
225                var _this_frame_contentDocument_documentElement;
226                return (_this_frame_contentDocument_documentElement = (_this_frame = this.frame()) === null || _this_frame === void 0 ? void 0 : (_this_frame_contentDocument = _this_frame.contentDocument) === null || _this_frame_contentDocument === void 0 ? void 0 : _this_frame_contentDocument.documentElement) !== null && _this_frame_contentDocument_documentElement !== void 0 ? _this_frame_contentDocument_documentElement : null;
227            }
228        },
229        {
230            key: "mode",
231            value: function mode() {
232                var checked = this.element.querySelector('input[type="radio"][name$="[mode]"]:checked');
233                var _checked_value;
234                return (_checked_value = checked === null || checked === void 0 ? void 0 : checked.value) !== null && _checked_value !== void 0 ? _checked_value : "default";
235            }
236        },
237        {
238            key: "syncSections",
239            value: function syncSections() {
240                var mode = this.mode();
241                this.presetSectionTarget.hidden = mode !== "preset";
242                this.customSectionTarget.hidden = mode !== "custom";
243                this.expertSectionTarget.hidden = mode !== "expert";
244                this.optionsSectionTarget.hidden = mode === "default";
245            }
246        },
247        {
248            key: "preview",
249            value: function preview() {
250                var _this = this;
251                this.clearPreview();
252                var mode = this.mode();
253                if (mode === "default") {
254                    return;
255                }
256                if (mode === "preset") {
257                    // Presets preview exactly: the server ships the resolved CSS
258                    // vars per scheme on the choice (data-tokens, see
259                    // ThemeType::presetCssVars), so what the preview shows is
260                    // byte-identical to what saving renders. Inline vars can't be
261                    // scheme-scoped, so pick the map matching the current scheme —
262                    // the scheme-toggle event re-runs this.
263                    var preset = this.element.querySelector('input[type="radio"][name$="[presetId]"]:checked');
264                    var json = preset === null || preset === void 0 ? void 0 : preset.dataset.tokens;
265                    if (json) {
266                        var tokens = JSON.parse(json);
267                        var scheme = this.isDark() ? "dark" : "light";
268                        var _tokens_scheme;
269                        Object.entries((_tokens_scheme = tokens[scheme]) !== null && _tokens_scheme !== void 0 ? _tokens_scheme : {}
269).forEach(function(param) {
270                            var _param = _sliced_to_array(param, 2), name = _param[0], value = _param[1];
271                            _this.setVar(name, value);
272                        });
273                    }
274                } else if (mode === "custom") {
275                    this.previewCustom();
276                } else if (mode === "expert") {
277                    this.previewExpertTokens();
278                }
279                this.previewRadiusAndFont();
280            }
281        },
282        {
283            key: "isDark",
284            value: function isDark() {
285                var _this_previewRoot;
286                var _this_previewRoot_classList_contains;
287                return (_this_previewRoot_classList_contains = (_this_previewRoot = this.previewRoot()) === null || _this_previewRoot === void 0 ? void 0 : _this_previewRoot.classList.contains("dark")) !== null && _this_previewRoot_classList_contains !== void 0 ? _this_previewRoot_classList_contains : false;
288            }
289        },
290        {
291            key: "previewCustom",
292            value: /**
293     * Exact custom-mode preview: run the same accent + surface ramps the
294     * server does (lib/theme-ramp.ts), then write the tokens for the current
295     * scheme. Mirrors ThemeCssRenderer's Custom branch — accent `root` rides
296     * in every scheme; `light`/`dark` (and the surface family, when a
297     * background is picked) are scheme-scoped.
298     */ function previewCustom() {
299                var _this_element_querySelector, _this_element_querySelector1;
300                var scheme = this.isDark() ? "dark" : "light";
301                var _this_element_querySelector_value;
302                var accent = (_this_element_querySelector_value = (_this_element_querySelector = this.element.querySelector('input[type="color"][name$="[accent]"]')) === null || _this_element_querySelector === void 0 ? void 0 : _this_element_querySelector.value) !== null && _this_element_querySelector_value !== void 0 ? _this_element_querySelector_value : "";
303                if (!/^#[0-9a-f]{6}$/i.test(accent)) {
304                    return;
305                }
306                var ramp = accentRamp(accent);
307                var tokens = _object_spread({}, ramp.root, ramp[scheme]);
308                var _this_element_querySelector_value1;
309                var background = (_this_element_querySelector_value1 = (_this_element_querySelector1 = this.element.querySelector('input[type="color"][name$="[background]"]')) === null || _this_element_querySelector1 === void 0 ? void 0 : _this_element_querySelector1.value) !== null && _this_element_querySelector_value1 !== void 0 ? _this_element_querySelector_value1 : "";
310                // The stock value means "no surface override" (ThemeDto stores it as
311                // null); skip it so an accent-only edit leaves the surfaces alone.
312                var pickedBackground = /^#[0-9a-f]{6}$/i.test(background) && background.toLowerCase() !== STOCK_BACKGROUND ? background : null;
313                if (pickedBackground !== null) {
314                    Object.assign(tokens, surfaceRamp(pickedBackground)[scheme]);
315                }
316                // Terminal chrome is scheme-stable, so it is applied whole — not
317                // scheme-picked — mirroring the renderer's root bucket.
318                Object.assign(tokens, terminalRamp(accent, pickedBackground));
319                var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
320                try {
321                    for(var _iterator = Object.entries(tokens)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
322                        var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], value = _step_value[1];
323                        this.setVar("--".concat(key), value);
324                    }
325                } catch (err) {
326                    _didIteratorError = true;
327                    _iteratorError = err;
328                } finally{
329                    try {
330                        if (!_iteratorNormalCompletion && _iterator.return != null) {
331                            _iterator.return();
332                        }
333                    } finally{
334                        if (_didIteratorError) {
335                            throw _iteratorError;
336                        }
337                    }
338                }
339            }
340        },
341        {
342            key: "previewExpertTokens",
343            value: function previewExpertTokens() {
344                var _this = this;
345                var scheme = this.isDark() ? "dark" : "light";
346                // Mirrors the server's per-type validation (Theme::*_PATTERN): a
347                // color with an optional alpha byte, a length, or a shadow. Anything
348                // else (a half-typed value) is simply not previewed yet.
349                var patterns = [
350                    /^#[0-9a-f]{6}(?:[0-9a-f]{2})?$/i,
351                    /^(?:0|\d{1,3}(?:\.\d{1,2})?(?:px|rem|em))$/,
352                    /^(?:0|-?\d{1,3}px)(?: (?:0|-?\d{1,3}px)){1,3} (?:#[0-9a-f]{6}(?:[0-9a-f]{2})?|rgba\(\d{1,3}, \d{1,3}, \d{1,3}, (?:0|1|0?\.\d{1,3})\))$/i
353                ];
354                this.element.querySelectorAll('[data-css-var][data-scheme="'.concat(scheme, '"]')).forEac
354h(function(input) {
355                    var _input_dataset_cssVar;
356                    var cssVar = (_input_dataset_cssVar = input.dataset.cssVar) !== null && _input_dataset_cssVar !== void 0 ? _input_dataset_cssVar : "";
357                    var value = input.value.trim();
358                    if (patterns.some(function(pattern) {
359                        return pattern.test(value);
360                    })) {
361                        _this.setVar(cssVar, value);
362                    }
363                });
364            }
365        },
366        {
367            key: "previewRadiusAndFont",
368            value: function previewRadiusAndFont() {
369                var _this = this;
370                var _radius_selectedOptions_, _font_selectedOptions_;
371                var radius = this.element.querySelector('select[name$="[radius]"]');
372                var radiusTokens = radius === null || radius === void 0 ? void 0 : (_radius_selectedOptions_ = radius.selectedOptions[0]) === null || _radius_selectedOptions_ === void 0 ? void 0 : _radius_selectedOptions_.dataset.tokens;
373                if (radiusTokens) {
374                    var tokens = JSON.parse(radiusTokens);
375                    Object.entries(tokens).forEach(function(param) {
376                        var _param = _sliced_to_array(param, 2), key = _param[0], value = _param[1];
377                        return _this.setVar("--".concat(key), value);
378                    });
379                }
380                var font = this.element.querySelector('select[name$="[font]"]');
381                var fontFamily = font === null || font === void 0 ? void 0 : (_font_selectedOptions_ = font.selectedOptions[0]) === null || _font_selectedOptions_ === void 0 ? void 0 : _font_selectedOptions_.dataset.fontFamily;
382                if (fontFamily) {
383                    this.setVar("--font-sans", fontFamily);
384                }
385            }
386        },
387        {
388            key: "setVar",
389            value: function setVar(name, value) {
390                var _this_previewRoot;
391                (_this_previewRoot = this.previewRoot()) === null || _this_previewRoot === void 0 ? void 0 : _this_previewRoot.style.setProperty(name, value);
392                this.appliedVars.add(name);
393            }
394        },
395        {
396            key: "clearPreview",
397            value: function clearPreview() {
398                var root = this.previewRoot();
399                this.appliedVars.forEach(function(name) {
400                    root === null || root === void 0 ? void 0 : root.style.removeProperty(name);
401                });
402                this.appliedVars.clear();
403            }
404        }
405    ]);
406    return _class;
407}(Controller);
408_define_property(_class, "targets", [
409    "presetSection",
410    "customSection",
411    "optionsSection",
412    "expertSection"
413]);
414_define_property(_class, "values", {
415    frame: String
416});
417/**
418 * Drives the shared theme editor (ThemeType, rendered by the `theme_widget`
419 * block in templates/theme.html.twig):
420 *
421 * - shows only the section(s) belonging to the checked mode radio;
422 * - live-previews edits by writing CSS custom properties inline on <html>,
423 *   where they outrank both the stock token bridge and the server-emitted
424 *   theme overrides.
425 *
426 * When the `frame` value is set (a CSS selector for a same-origin
427 * <iframe>, wired through ThemeType's `preview_frame` option) the preview
428 * writes into the iframe's <html> instead of this page's — used by the
429 * IdentityService style page, whose preview box shows the auth pages'
430 * look without retheming the panel page around it.
431 *
432 * The custom-mode preview is exact, not a heuristic: `lib/theme-ramp.ts` is
433 * a faithful port of the server's AccentRampGenerator + SurfaceRampGenerator,
434 * so the vars written here are byte-identical to what saving renders (presets
435 * were already exact via server-shipped data-tokens). Inline vars can't be
436 * scheme-scoped, so — like presets — only the map matching the preview's
437 * current scheme is applied, and the scheme toggle re-runs this. The server
438 * render stays authoritative: the preview is cleared on disconnect and
439 * rebuilt from the saved theme on the next page load.
440 */ export { _class as default };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.