@aicut/core 0.2.0 → 0.4.0

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.
@@ -15,11 +15,6 @@ interface LightingLocale {
15
15
  lightingRim: string;
16
16
  lightingViewPerspective: string;
17
17
  lightingViewFront: string;
18
- lightingResetParams: string;
19
- /** Aria label / tooltip for the × button that closes the Smart panel. */
20
- lightingSmartClose: string;
21
- /** Tooltip / label for the controls-header Smart Mode toggle. */
22
- lightingSmartToggle: string;
23
18
  lightingDirLeft: string;
24
19
  lightingDirRight: string;
25
20
  lightingDirTop: string;
@@ -67,47 +62,26 @@ interface LightingEditorOptions {
67
62
  config?: Partial<LightingConfig>;
68
63
  /** Initial camera view. Default `"perspective"`. */
69
64
  view?: LightingView;
70
- /**
71
- * Whether the Smart Mode feature is wired in at all. When false the
72
- * slot column never renders and the controls header hides the
73
- * Smart Mode toggle — the layout becomes a clean 2-column
74
- * (scene + controls). Default `true`.
75
- */
76
- smartEnabled?: boolean;
77
- /**
78
- * When `smartEnabled` is true, whether the Smart Mode slot panel
79
- * starts open. Hosts toggle later via `api.setSmartOpen(bool)` or
80
- * by clicking the library-rendered × button. Default `true`.
81
- */
82
- smartOpen?: boolean;
83
65
  /** Theme tokens — same shape as the video Editor's theme. */
84
66
  theme?: Theme;
85
67
  /** Locale overrides on top of English defaults (`localeEn` + `lightingLocaleEn`). */
86
68
  locale?: Partial<Locale & LightingLocale>;
87
69
  /** Fires on any config mutation (drag, slider, preset click, toggle). */
88
70
  onChange?: (cfg: LightingConfig) => void;
89
- /**
90
- * Surface event for the host's own "Generate" button — the library
91
- * never wires this. Use `api.requestGenerate()` from your UI.
92
- */
93
- onGenerate?: (cfg: LightingConfig) => void;
94
- /** Fires when the user toggles the Smart Mode panel via × / toggle. */
95
- onSmartOpenChange?: (open: boolean) => void;
96
71
  }
97
72
  /** Safe, conservative defaults for first mount. */
98
73
  declare const DEFAULT_LIGHTING_CONFIG: LightingConfig;
99
74
 
100
75
  /**
101
- * Top-level lighting picker. Mirrors `Editor`'s lifecycle `static
102
- * create(opts)`, wipes the container, owns DOM + WebGL, exposes
103
- * `destroy()` and reactive `setTheme` / `setLocale`. Separate from
104
- * the video Editor; the two can coexist in the same host page.
76
+ * Top-level lighting picker. Two columns: a 3D scene (sphere + subject
77
+ * plane + draggable light dot + cone beam) and a controls panel
78
+ * (brightness / color / 6-direction key-light grid / rim toggle).
105
79
  *
106
- * Layout (left right):
107
- * [scene 240px] [controls 220px] [smartSlot (drawer)]
108
- * The smart slot is host-supplied. Library renders a × close button
109
- * + a "Smart mode" toggle in the controls header when the slot is
110
- * available; `smartEnabled: false` removes the slot entirely.
80
+ * Deliberately scoped to JUST the picker — the host owns everything
81
+ * around it (smart-mode UI, generate buttons, layout, close handling,
82
+ * theming above the editor). Render <LightingEditor> alongside your
83
+ * own Smart panel in your own flex/grid; the library doesn't try to
84
+ * model "open / closed drawer" semantics for you.
111
85
  */
112
86
  declare class LightingEditor {
113
87
  private root;
@@ -115,22 +89,14 @@ declare class LightingEditor {
115
89
  private config;
116
90
  private view;
117
91
  private locale;
118
- private smartEnabled;
119
- private smartOpen;
120
92
  private scene;
121
93
  private controls;
122
94
  private sceneViewport;
123
95
  private viewToggleEl;
124
- private body;
125
- private smartWrapper;
126
- private smartCloseBtn;
127
- private smartToggleEl;
128
- private smartToggleThumb;
129
- /** Host slot the React/Vue wrapper portals/teleports into. Stable
130
- * reference across smartOpen toggles — only the wrapper around it
131
- * collapses/expands. Always present even when `smartEnabled: false`
132
- * so portals don't blow up; just detached from the visible tree. */
133
- readonly smartSlot: HTMLDivElement;
96
+ /** Footer slot in the controls column. Host appends Reset/Generate/
97
+ * preset-save/etc. buttons here. The library renders nothing into
98
+ * it — it's the same convention as the video editor's toolbar slots. */
99
+ readonly controlsFooter: HTMLDivElement;
134
100
  private resizeObs;
135
101
  private destroyed;
136
102
  static create(opts: LightingEditorOptions): LightingEditor;
@@ -138,35 +104,17 @@ declare class LightingEditor {
138
104
  getConfig(): LightingConfig;
139
105
  setConfig(partial: Partial<LightingConfig>, _reason?: "external" | "reset"): void;
140
106
  setSubjectImage(url: string): void;
107
+ /** Restore config to the safe defaults. Convenience for host's
108
+ * "Reset" button — equivalent to `setConfig(DEFAULT_LIGHTING_CONFIG)`. */
109
+ reset(): void;
141
110
  setView(v: LightingView): void;
142
111
  getView(): LightingView;
143
- /** Enable/disable the entire Smart Mode feature at runtime. */
144
- setSmartEnabled(enabled: boolean): void;
145
- isSmartEnabled(): boolean;
146
- /** Open/close the smart slot drawer when enabled. No-op when disabled. */
147
- setSmartOpen(open: boolean): void;
148
- isSmartOpen(): boolean;
149
112
  setTheme(theme: Theme): void;
150
113
  setLocale(locale: Partial<Locale & LightingLocale>): void;
151
- requestGenerate(): void;
152
114
  destroy(): void;
153
115
  private applyMutation;
154
116
  private buildViewToggle;
155
117
  private syncViewToggle;
156
- /**
157
- * Build the smart slot column wrapper: × close button + the actual
158
- * host slot. Wrapper handles the drawer animation; slot reference
159
- * stays stable so portals don't have to relocate.
160
- */
161
- private buildSmartWrapper;
162
- /** Pill-style toggle that lives in the controls header. Re-opens
163
- * the smart drawer when the host has closed it via ×. */
164
- private buildSmartToggle;
165
- /** Re-translate smart-related labels after a locale swap. */
166
- private syncSmartLocale;
167
- /** Mirror smart state to data-* attrs + toggle thumb position.
168
- * Drives the CSS that collapses the column when closed. */
169
- private syncSmartState;
170
118
  }
171
119
 
172
120
  /**
@@ -15,11 +15,6 @@ interface LightingLocale {
15
15
  lightingRim: string;
16
16
  lightingViewPerspective: string;
17
17
  lightingViewFront: string;
18
- lightingResetParams: string;
19
- /** Aria label / tooltip for the × button that closes the Smart panel. */
20
- lightingSmartClose: string;
21
- /** Tooltip / label for the controls-header Smart Mode toggle. */
22
- lightingSmartToggle: string;
23
18
  lightingDirLeft: string;
24
19
  lightingDirRight: string;
25
20
  lightingDirTop: string;
@@ -67,47 +62,26 @@ interface LightingEditorOptions {
67
62
  config?: Partial<LightingConfig>;
68
63
  /** Initial camera view. Default `"perspective"`. */
69
64
  view?: LightingView;
70
- /**
71
- * Whether the Smart Mode feature is wired in at all. When false the
72
- * slot column never renders and the controls header hides the
73
- * Smart Mode toggle — the layout becomes a clean 2-column
74
- * (scene + controls). Default `true`.
75
- */
76
- smartEnabled?: boolean;
77
- /**
78
- * When `smartEnabled` is true, whether the Smart Mode slot panel
79
- * starts open. Hosts toggle later via `api.setSmartOpen(bool)` or
80
- * by clicking the library-rendered × button. Default `true`.
81
- */
82
- smartOpen?: boolean;
83
65
  /** Theme tokens — same shape as the video Editor's theme. */
84
66
  theme?: Theme;
85
67
  /** Locale overrides on top of English defaults (`localeEn` + `lightingLocaleEn`). */
86
68
  locale?: Partial<Locale & LightingLocale>;
87
69
  /** Fires on any config mutation (drag, slider, preset click, toggle). */
88
70
  onChange?: (cfg: LightingConfig) => void;
89
- /**
90
- * Surface event for the host's own "Generate" button — the library
91
- * never wires this. Use `api.requestGenerate()` from your UI.
92
- */
93
- onGenerate?: (cfg: LightingConfig) => void;
94
- /** Fires when the user toggles the Smart Mode panel via × / toggle. */
95
- onSmartOpenChange?: (open: boolean) => void;
96
71
  }
97
72
  /** Safe, conservative defaults for first mount. */
98
73
  declare const DEFAULT_LIGHTING_CONFIG: LightingConfig;
99
74
 
100
75
  /**
101
- * Top-level lighting picker. Mirrors `Editor`'s lifecycle `static
102
- * create(opts)`, wipes the container, owns DOM + WebGL, exposes
103
- * `destroy()` and reactive `setTheme` / `setLocale`. Separate from
104
- * the video Editor; the two can coexist in the same host page.
76
+ * Top-level lighting picker. Two columns: a 3D scene (sphere + subject
77
+ * plane + draggable light dot + cone beam) and a controls panel
78
+ * (brightness / color / 6-direction key-light grid / rim toggle).
105
79
  *
106
- * Layout (left right):
107
- * [scene 240px] [controls 220px] [smartSlot (drawer)]
108
- * The smart slot is host-supplied. Library renders a × close button
109
- * + a "Smart mode" toggle in the controls header when the slot is
110
- * available; `smartEnabled: false` removes the slot entirely.
80
+ * Deliberately scoped to JUST the picker — the host owns everything
81
+ * around it (smart-mode UI, generate buttons, layout, close handling,
82
+ * theming above the editor). Render <LightingEditor> alongside your
83
+ * own Smart panel in your own flex/grid; the library doesn't try to
84
+ * model "open / closed drawer" semantics for you.
111
85
  */
112
86
  declare class LightingEditor {
113
87
  private root;
@@ -115,22 +89,14 @@ declare class LightingEditor {
115
89
  private config;
116
90
  private view;
117
91
  private locale;
118
- private smartEnabled;
119
- private smartOpen;
120
92
  private scene;
121
93
  private controls;
122
94
  private sceneViewport;
123
95
  private viewToggleEl;
124
- private body;
125
- private smartWrapper;
126
- private smartCloseBtn;
127
- private smartToggleEl;
128
- private smartToggleThumb;
129
- /** Host slot the React/Vue wrapper portals/teleports into. Stable
130
- * reference across smartOpen toggles — only the wrapper around it
131
- * collapses/expands. Always present even when `smartEnabled: false`
132
- * so portals don't blow up; just detached from the visible tree. */
133
- readonly smartSlot: HTMLDivElement;
96
+ /** Footer slot in the controls column. Host appends Reset/Generate/
97
+ * preset-save/etc. buttons here. The library renders nothing into
98
+ * it — it's the same convention as the video editor's toolbar slots. */
99
+ readonly controlsFooter: HTMLDivElement;
134
100
  private resizeObs;
135
101
  private destroyed;
136
102
  static create(opts: LightingEditorOptions): LightingEditor;
@@ -138,35 +104,17 @@ declare class LightingEditor {
138
104
  getConfig(): LightingConfig;
139
105
  setConfig(partial: Partial<LightingConfig>, _reason?: "external" | "reset"): void;
140
106
  setSubjectImage(url: string): void;
107
+ /** Restore config to the safe defaults. Convenience for host's
108
+ * "Reset" button — equivalent to `setConfig(DEFAULT_LIGHTING_CONFIG)`. */
109
+ reset(): void;
141
110
  setView(v: LightingView): void;
142
111
  getView(): LightingView;
143
- /** Enable/disable the entire Smart Mode feature at runtime. */
144
- setSmartEnabled(enabled: boolean): void;
145
- isSmartEnabled(): boolean;
146
- /** Open/close the smart slot drawer when enabled. No-op when disabled. */
147
- setSmartOpen(open: boolean): void;
148
- isSmartOpen(): boolean;
149
112
  setTheme(theme: Theme): void;
150
113
  setLocale(locale: Partial<Locale & LightingLocale>): void;
151
- requestGenerate(): void;
152
114
  destroy(): void;
153
115
  private applyMutation;
154
116
  private buildViewToggle;
155
117
  private syncViewToggle;
156
- /**
157
- * Build the smart slot column wrapper: × close button + the actual
158
- * host slot. Wrapper handles the drawer animation; slot reference
159
- * stays stable so portals don't have to relocate.
160
- */
161
- private buildSmartWrapper;
162
- /** Pill-style toggle that lives in the controls header. Re-opens
163
- * the smart drawer when the host has closed it via ×. */
164
- private buildSmartToggle;
165
- /** Re-translate smart-related labels after a locale swap. */
166
- private syncSmartLocale;
167
- /** Mirror smart state to data-* attrs + toggle thumb position.
168
- * Drives the CSS that collapses the column when closed. */
169
- private syncSmartState;
170
118
  }
171
119
 
172
120
  /**
@@ -33,6 +33,13 @@ var LightingControls = class {
33
33
  /** Exposed so the editor can append host-level chrome (e.g. the
34
34
  * Smart Mode toggle) without LightingControls knowing about it. */
35
35
  headerSlot;
36
+ /**
37
+ * Footer slot — sits where the built-in Reset used to live. Host
38
+ * appends any action buttons (Reset, Generate, Save preset, etc.)
39
+ * via the React wrapper's `controlsFooter` prop / Vue's
40
+ * `<slot name="controlsFooter">`. Library renders nothing here.
41
+ */
42
+ footerSlot;
36
43
  brightnessInput;
37
44
  colorInput;
38
45
  dirButtons;
@@ -45,7 +52,6 @@ var LightingControls = class {
45
52
  colorLabelEl;
46
53
  keyLabelEl;
47
54
  rimLabelEl;
48
- resetBtn;
49
55
  locale;
50
56
  lastConfig = null;
51
57
  constructor(locale, cb) {
@@ -135,15 +141,12 @@ var LightingControls = class {
135
141
  });
136
142
  rimSection.appendChild(this.rimToggle);
137
143
  this.root.appendChild(rimSection);
138
- const footer = mkDiv("aicut-lighting-section aicut-lighting-section-row");
139
- this.resetBtn = document.createElement("button");
140
- this.resetBtn.type = "button";
141
- this.resetBtn.className = "aicut-lighting-reset";
142
- this.resetBtn.textContent = locale.lightingResetParams;
143
- this.resetBtn.setAttribute("data-testid", "aicut-lighting-reset");
144
- this.resetBtn.addEventListener("click", () => cb.onReset());
145
- footer.appendChild(this.resetBtn);
146
- this.root.appendChild(footer);
144
+ this.footerSlot = mkDiv("aicut-lighting-controls-footer");
145
+ this.footerSlot.setAttribute(
146
+ "data-testid",
147
+ "aicut-lighting-controls-footer"
148
+ );
149
+ this.root.appendChild(this.footerSlot);
147
150
  }
148
151
  /** Idempotent — mirror the given config into all visible controls. */
149
152
  render(cfg) {
@@ -172,7 +175,6 @@ var LightingControls = class {
172
175
  this.colorLabelEl.textContent = locale.lightingColor;
173
176
  this.keyLabelEl.textContent = locale.lightingKeyTitle;
174
177
  this.rimLabelEl.textContent = locale.lightingRim;
175
- this.resetBtn.textContent = locale.lightingResetParams;
176
178
  const dirLabels = {
177
179
  left: "lightingDirLeft",
178
180
  right: "lightingDirRight",
@@ -208,9 +210,6 @@ var lightingLocaleEn = {
208
210
  lightingRim: "Rim light",
209
211
  lightingViewPerspective: "Perspective",
210
212
  lightingViewFront: "Front",
211
- lightingResetParams: "Reset",
212
- lightingSmartClose: "Close Smart mode",
213
- lightingSmartToggle: "Smart mode",
214
213
  lightingDirLeft: "Left",
215
214
  lightingDirRight: "Right",
216
215
  lightingDirTop: "Top",
@@ -227,9 +226,6 @@ var lightingLocaleZh = {
227
226
  lightingRim: "\u8F6E\u5ED3\u5149",
228
227
  lightingViewPerspective: "\u900F\u89C6",
229
228
  lightingViewFront: "\u6B63\u9762",
230
- lightingResetParams: "\u91CD\u7F6E\u53C2\u6570",
231
- lightingSmartClose: "\u5173\u95ED\u667A\u80FD\u6A21\u5F0F",
232
- lightingSmartToggle: "\u667A\u80FD\u6A21\u5F0F",
233
229
  lightingDirLeft: "\u5DE6\u4FA7",
234
230
  lightingDirRight: "\u53F3\u4FA7",
235
231
  lightingDirTop: "\u9876\u90E8",
@@ -18984,22 +18980,14 @@ var LightingEditor = class _LightingEditor {
18984
18980
  config;
18985
18981
  view;
18986
18982
  locale;
18987
- smartEnabled;
18988
- smartOpen;
18989
18983
  scene;
18990
18984
  controls;
18991
18985
  sceneViewport;
18992
18986
  viewToggleEl;
18993
- body;
18994
- smartWrapper = null;
18995
- smartCloseBtn = null;
18996
- smartToggleEl = null;
18997
- smartToggleThumb = null;
18998
- /** Host slot the React/Vue wrapper portals/teleports into. Stable
18999
- * reference across smartOpen toggles — only the wrapper around it
19000
- * collapses/expands. Always present even when `smartEnabled: false`
19001
- * so portals don't blow up; just detached from the visible tree. */
19002
- smartSlot;
18987
+ /** Footer slot in the controls column. Host appends Reset/Generate/
18988
+ * preset-save/etc. buttons here. The library renders nothing into
18989
+ * it it's the same convention as the video editor's toolbar slots. */
18990
+ controlsFooter;
19003
18991
  resizeObs = null;
19004
18992
  destroyed = false;
19005
18993
  static create(opts) {
@@ -19010,8 +18998,6 @@ var LightingEditor = class _LightingEditor {
19010
18998
  this.root = opts.container;
19011
18999
  this.config = { ...DEFAULT_LIGHTING_CONFIG, ...opts.config };
19012
19000
  this.view = opts.view ?? "perspective";
19013
- this.smartEnabled = opts.smartEnabled !== false;
19014
- this.smartOpen = opts.smartOpen !== false;
19015
19001
  this.locale = {
19016
19002
  ...mergeLocale(opts.locale),
19017
19003
  ...mergeLightingLocale(opts.locale)
@@ -19020,9 +19006,9 @@ var LightingEditor = class _LightingEditor {
19020
19006
  this.root.innerHTML = "";
19021
19007
  if (!this.root.style.position) this.root.style.position = "relative";
19022
19008
  applyTheme(this.root, opts.theme);
19023
- this.body = document.createElement("div");
19024
- this.body.className = "aicut-lighting-body";
19025
- this.root.appendChild(this.body);
19009
+ const body = document.createElement("div");
19010
+ body.className = "aicut-lighting-body";
19011
+ this.root.appendChild(body);
19026
19012
  const sceneCol = document.createElement("div");
19027
19013
  sceneCol.className = "aicut-lighting-scene-col";
19028
19014
  this.viewToggleEl = this.buildViewToggle();
@@ -19031,7 +19017,7 @@ var LightingEditor = class _LightingEditor {
19031
19017
  this.sceneViewport.className = "aicut-lighting-scene-viewport";
19032
19018
  this.sceneViewport.setAttribute("data-testid", "aicut-lighting-scene");
19033
19019
  sceneCol.appendChild(this.sceneViewport);
19034
- this.body.appendChild(sceneCol);
19020
+ body.appendChild(sceneCol);
19035
19021
  this.controls = new LightingControls(this.locale, {
19036
19022
  onBrightnessChange: (level) => this.applyMutation({ brightness: level }),
19037
19023
  onColorChange: (hex) => this.applyMutation({ color: hex }),
@@ -19039,20 +19025,10 @@ var LightingEditor = class _LightingEditor {
19039
19025
  keyDirection: PRESET_DIRECTIONS[preset],
19040
19026
  keyPreset: preset
19041
19027
  }),
19042
- onRimToggle: (on) => this.applyMutation({ rim: on }),
19043
- onReset: () => this.setConfig(DEFAULT_LIGHTING_CONFIG, "reset")
19028
+ onRimToggle: (on) => this.applyMutation({ rim: on })
19044
19029
  });
19045
- this.body.appendChild(this.controls.root);
19046
- this.smartSlot = document.createElement("div");
19047
- this.smartSlot.className = "aicut-lighting-smart-slot";
19048
- this.smartSlot.setAttribute("data-testid", "aicut-lighting-smart");
19049
- if (this.smartEnabled) {
19050
- this.smartWrapper = this.buildSmartWrapper();
19051
- this.body.appendChild(this.smartWrapper);
19052
- this.smartToggleEl = this.buildSmartToggle();
19053
- this.controls.headerSlot.appendChild(this.smartToggleEl);
19054
- }
19055
- this.syncSmartState();
19030
+ body.appendChild(this.controls.root);
19031
+ this.controlsFooter = this.controls.footerSlot;
19056
19032
  this.scene = new LightingScene(this.sceneViewport, this.view);
19057
19033
  this.scene.setLightDirection(this.config.keyDirection);
19058
19034
  this.scene.setBrightness(this.config.brightness);
@@ -19096,6 +19072,11 @@ var LightingEditor = class _LightingEditor {
19096
19072
  this.opts.subjectImageUrl = url;
19097
19073
  this.scene.setSubjectImage(url);
19098
19074
  }
19075
+ /** Restore config to the safe defaults. Convenience for host's
19076
+ * "Reset" button — equivalent to `setConfig(DEFAULT_LIGHTING_CONFIG)`. */
19077
+ reset() {
19078
+ this.setConfig(DEFAULT_LIGHTING_CONFIG, "reset");
19079
+ }
19099
19080
  setView(v) {
19100
19081
  if (v === this.view) return;
19101
19082
  this.view = v;
@@ -19105,42 +19086,6 @@ var LightingEditor = class _LightingEditor {
19105
19086
  getView() {
19106
19087
  return this.view;
19107
19088
  }
19108
- /** Enable/disable the entire Smart Mode feature at runtime. */
19109
- setSmartEnabled(enabled) {
19110
- if (enabled === this.smartEnabled) return;
19111
- this.smartEnabled = enabled;
19112
- if (enabled) {
19113
- if (!this.smartWrapper) {
19114
- this.smartWrapper = this.buildSmartWrapper();
19115
- this.body.appendChild(this.smartWrapper);
19116
- }
19117
- if (!this.smartToggleEl) {
19118
- this.smartToggleEl = this.buildSmartToggle();
19119
- this.controls.headerSlot.appendChild(this.smartToggleEl);
19120
- }
19121
- } else {
19122
- this.smartWrapper?.remove();
19123
- this.smartWrapper = null;
19124
- this.smartCloseBtn = null;
19125
- this.smartToggleEl?.remove();
19126
- this.smartToggleEl = null;
19127
- this.smartToggleThumb = null;
19128
- }
19129
- this.syncSmartState();
19130
- }
19131
- isSmartEnabled() {
19132
- return this.smartEnabled;
19133
- }
19134
- /** Open/close the smart slot drawer when enabled. No-op when disabled. */
19135
- setSmartOpen(open) {
19136
- if (!this.smartEnabled || open === this.smartOpen) return;
19137
- this.smartOpen = open;
19138
- this.syncSmartState();
19139
- this.opts.onSmartOpenChange?.(open);
19140
- }
19141
- isSmartOpen() {
19142
- return this.smartOpen;
19143
- }
19144
19089
  setTheme(theme) {
19145
19090
  applyTheme(this.root, theme);
19146
19091
  }
@@ -19151,10 +19096,6 @@ var LightingEditor = class _LightingEditor {
19151
19096
  };
19152
19097
  this.controls.setLocale(this.locale);
19153
19098
  this.syncViewToggle();
19154
- this.syncSmartLocale();
19155
- }
19156
- requestGenerate() {
19157
- this.opts.onGenerate?.(this.getConfig());
19158
19099
  }
19159
19100
  destroy() {
19160
19101
  if (this.destroyed) return;
@@ -19163,8 +19104,6 @@ var LightingEditor = class _LightingEditor {
19163
19104
  this.scene.destroy();
19164
19105
  this.root.innerHTML = "";
19165
19106
  this.root.classList.remove("aicut-root", "aicut-lighting-editor");
19166
- this.root.removeAttribute("data-smart-enabled");
19167
- this.root.removeAttribute("data-smart-open");
19168
19107
  }
19169
19108
  // ---- Internal ------------------------------------------------------
19170
19109
  applyMutation(partial) {
@@ -19214,86 +19153,6 @@ var LightingEditor = class _LightingEditor {
19214
19153
  if (v === "front") btn.textContent = this.locale.lightingViewFront;
19215
19154
  }
19216
19155
  }
19217
- /**
19218
- * Build the smart slot column wrapper: × close button + the actual
19219
- * host slot. Wrapper handles the drawer animation; slot reference
19220
- * stays stable so portals don't have to relocate.
19221
- */
19222
- buildSmartWrapper() {
19223
- const wrap = document.createElement("div");
19224
- wrap.className = "aicut-lighting-smart-wrapper";
19225
- this.smartCloseBtn = document.createElement("button");
19226
- this.smartCloseBtn.type = "button";
19227
- this.smartCloseBtn.className = "aicut-lighting-smart-close";
19228
- this.smartCloseBtn.title = this.locale.lightingSmartClose;
19229
- this.smartCloseBtn.setAttribute("aria-label", this.locale.lightingSmartClose);
19230
- this.smartCloseBtn.setAttribute("data-testid", "aicut-lighting-smart-close");
19231
- this.smartCloseBtn.innerHTML = "&times;";
19232
- this.smartCloseBtn.addEventListener("click", () => this.setSmartOpen(false));
19233
- wrap.appendChild(this.smartCloseBtn);
19234
- wrap.appendChild(this.smartSlot);
19235
- return wrap;
19236
- }
19237
- /** Pill-style toggle that lives in the controls header. Re-opens
19238
- * the smart drawer when the host has closed it via ×. */
19239
- buildSmartToggle() {
19240
- const row = document.createElement("div");
19241
- row.className = "aicut-lighting-smart-toggle-row";
19242
- const label = document.createElement("span");
19243
- label.className = "aicut-lighting-smart-toggle-label";
19244
- label.textContent = this.locale.lightingSmartToggle;
19245
- row.appendChild(label);
19246
- const toggle = document.createElement("div");
19247
- toggle.className = "aicut-lighting-toggle aicut-lighting-smart-toggle";
19248
- toggle.setAttribute("role", "switch");
19249
- toggle.setAttribute("tabindex", "0");
19250
- toggle.setAttribute("data-testid", "aicut-lighting-smart-toggle");
19251
- toggle.title = this.locale.lightingSmartToggle;
19252
- this.smartToggleThumb = document.createElement("div");
19253
- this.smartToggleThumb.className = "aicut-lighting-toggle-thumb";
19254
- toggle.appendChild(this.smartToggleThumb);
19255
- toggle.addEventListener("click", () => this.setSmartOpen(!this.smartOpen));
19256
- row.appendChild(toggle);
19257
- return row;
19258
- }
19259
- /** Re-translate smart-related labels after a locale swap. */
19260
- syncSmartLocale() {
19261
- if (this.smartCloseBtn) {
19262
- this.smartCloseBtn.title = this.locale.lightingSmartClose;
19263
- this.smartCloseBtn.setAttribute("aria-label", this.locale.lightingSmartClose);
19264
- }
19265
- if (this.smartToggleEl) {
19266
- const label = this.smartToggleEl.querySelector(
19267
- ".aicut-lighting-smart-toggle-label"
19268
- );
19269
- if (label) label.textContent = this.locale.lightingSmartToggle;
19270
- const toggle = this.smartToggleEl.querySelector(
19271
- ".aicut-lighting-smart-toggle"
19272
- );
19273
- if (toggle) toggle.title = this.locale.lightingSmartToggle;
19274
- }
19275
- }
19276
- /** Mirror smart state to data-* attrs + toggle thumb position.
19277
- * Drives the CSS that collapses the column when closed. */
19278
- syncSmartState() {
19279
- this.root.setAttribute(
19280
- "data-smart-enabled",
19281
- this.smartEnabled ? "true" : "false"
19282
- );
19283
- this.root.setAttribute(
19284
- "data-smart-open",
19285
- this.smartOpen ? "true" : "false"
19286
- );
19287
- if (this.smartToggleEl) {
19288
- const toggle = this.smartToggleEl.querySelector(
19289
- ".aicut-lighting-smart-toggle"
19290
- );
19291
- if (toggle) {
19292
- toggle.classList.toggle("active", this.smartOpen);
19293
- toggle.setAttribute("aria-checked", this.smartOpen ? "true" : "false");
19294
- }
19295
- }
19296
- }
19297
19156
  };
19298
19157
  /*! Bundled license information:
19299
19158