@aicut/core 0.2.0 → 0.3.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.
@@ -16,10 +16,6 @@ interface LightingLocale {
16
16
  lightingViewPerspective: string;
17
17
  lightingViewFront: string;
18
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
19
  lightingDirLeft: string;
24
20
  lightingDirRight: string;
25
21
  lightingDirTop: string;
@@ -67,47 +63,26 @@ interface LightingEditorOptions {
67
63
  config?: Partial<LightingConfig>;
68
64
  /** Initial camera view. Default `"perspective"`. */
69
65
  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
66
  /** Theme tokens — same shape as the video Editor's theme. */
84
67
  theme?: Theme;
85
68
  /** Locale overrides on top of English defaults (`localeEn` + `lightingLocaleEn`). */
86
69
  locale?: Partial<Locale & LightingLocale>;
87
70
  /** Fires on any config mutation (drag, slider, preset click, toggle). */
88
71
  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
72
  }
97
73
  /** Safe, conservative defaults for first mount. */
98
74
  declare const DEFAULT_LIGHTING_CONFIG: LightingConfig;
99
75
 
100
76
  /**
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.
77
+ * Top-level lighting picker. Two columns: a 3D scene (sphere + subject
78
+ * plane + draggable light dot + cone beam) and a controls panel
79
+ * (brightness / color / 6-direction key-light grid / rim toggle).
105
80
  *
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.
81
+ * Deliberately scoped to JUST the picker — the host owns everything
82
+ * around it (smart-mode UI, generate buttons, layout, close handling,
83
+ * theming above the editor). Render <LightingEditor> alongside your
84
+ * own Smart panel in your own flex/grid; the library doesn't try to
85
+ * model "open / closed drawer" semantics for you.
111
86
  */
112
87
  declare class LightingEditor {
113
88
  private root;
@@ -115,22 +90,10 @@ declare class LightingEditor {
115
90
  private config;
116
91
  private view;
117
92
  private locale;
118
- private smartEnabled;
119
- private smartOpen;
120
93
  private scene;
121
94
  private controls;
122
95
  private sceneViewport;
123
96
  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;
134
97
  private resizeObs;
135
98
  private destroyed;
136
99
  static create(opts: LightingEditorOptions): LightingEditor;
@@ -140,33 +103,12 @@ declare class LightingEditor {
140
103
  setSubjectImage(url: string): void;
141
104
  setView(v: LightingView): void;
142
105
  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
106
  setTheme(theme: Theme): void;
150
107
  setLocale(locale: Partial<Locale & LightingLocale>): void;
151
- requestGenerate(): void;
152
108
  destroy(): void;
153
109
  private applyMutation;
154
110
  private buildViewToggle;
155
111
  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
112
  }
171
113
 
172
114
  /**
@@ -16,10 +16,6 @@ interface LightingLocale {
16
16
  lightingViewPerspective: string;
17
17
  lightingViewFront: string;
18
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
19
  lightingDirLeft: string;
24
20
  lightingDirRight: string;
25
21
  lightingDirTop: string;
@@ -67,47 +63,26 @@ interface LightingEditorOptions {
67
63
  config?: Partial<LightingConfig>;
68
64
  /** Initial camera view. Default `"perspective"`. */
69
65
  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
66
  /** Theme tokens — same shape as the video Editor's theme. */
84
67
  theme?: Theme;
85
68
  /** Locale overrides on top of English defaults (`localeEn` + `lightingLocaleEn`). */
86
69
  locale?: Partial<Locale & LightingLocale>;
87
70
  /** Fires on any config mutation (drag, slider, preset click, toggle). */
88
71
  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
72
  }
97
73
  /** Safe, conservative defaults for first mount. */
98
74
  declare const DEFAULT_LIGHTING_CONFIG: LightingConfig;
99
75
 
100
76
  /**
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.
77
+ * Top-level lighting picker. Two columns: a 3D scene (sphere + subject
78
+ * plane + draggable light dot + cone beam) and a controls panel
79
+ * (brightness / color / 6-direction key-light grid / rim toggle).
105
80
  *
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.
81
+ * Deliberately scoped to JUST the picker — the host owns everything
82
+ * around it (smart-mode UI, generate buttons, layout, close handling,
83
+ * theming above the editor). Render <LightingEditor> alongside your
84
+ * own Smart panel in your own flex/grid; the library doesn't try to
85
+ * model "open / closed drawer" semantics for you.
111
86
  */
112
87
  declare class LightingEditor {
113
88
  private root;
@@ -115,22 +90,10 @@ declare class LightingEditor {
115
90
  private config;
116
91
  private view;
117
92
  private locale;
118
- private smartEnabled;
119
- private smartOpen;
120
93
  private scene;
121
94
  private controls;
122
95
  private sceneViewport;
123
96
  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;
134
97
  private resizeObs;
135
98
  private destroyed;
136
99
  static create(opts: LightingEditorOptions): LightingEditor;
@@ -140,33 +103,12 @@ declare class LightingEditor {
140
103
  setSubjectImage(url: string): void;
141
104
  setView(v: LightingView): void;
142
105
  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
106
  setTheme(theme: Theme): void;
150
107
  setLocale(locale: Partial<Locale & LightingLocale>): void;
151
- requestGenerate(): void;
152
108
  destroy(): void;
153
109
  private applyMutation;
154
110
  private buildViewToggle;
155
111
  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
112
  }
171
113
 
172
114
  /**
@@ -209,8 +209,6 @@ var lightingLocaleEn = {
209
209
  lightingViewPerspective: "Perspective",
210
210
  lightingViewFront: "Front",
211
211
  lightingResetParams: "Reset",
212
- lightingSmartClose: "Close Smart mode",
213
- lightingSmartToggle: "Smart mode",
214
212
  lightingDirLeft: "Left",
215
213
  lightingDirRight: "Right",
216
214
  lightingDirTop: "Top",
@@ -228,8 +226,6 @@ var lightingLocaleZh = {
228
226
  lightingViewPerspective: "\u900F\u89C6",
229
227
  lightingViewFront: "\u6B63\u9762",
230
228
  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,10 @@ 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;
19003
18987
  resizeObs = null;
19004
18988
  destroyed = false;
19005
18989
  static create(opts) {
@@ -19010,8 +18994,6 @@ var LightingEditor = class _LightingEditor {
19010
18994
  this.root = opts.container;
19011
18995
  this.config = { ...DEFAULT_LIGHTING_CONFIG, ...opts.config };
19012
18996
  this.view = opts.view ?? "perspective";
19013
- this.smartEnabled = opts.smartEnabled !== false;
19014
- this.smartOpen = opts.smartOpen !== false;
19015
18997
  this.locale = {
19016
18998
  ...mergeLocale(opts.locale),
19017
18999
  ...mergeLightingLocale(opts.locale)
@@ -19020,9 +19002,9 @@ var LightingEditor = class _LightingEditor {
19020
19002
  this.root.innerHTML = "";
19021
19003
  if (!this.root.style.position) this.root.style.position = "relative";
19022
19004
  applyTheme(this.root, opts.theme);
19023
- this.body = document.createElement("div");
19024
- this.body.className = "aicut-lighting-body";
19025
- this.root.appendChild(this.body);
19005
+ const body = document.createElement("div");
19006
+ body.className = "aicut-lighting-body";
19007
+ this.root.appendChild(body);
19026
19008
  const sceneCol = document.createElement("div");
19027
19009
  sceneCol.className = "aicut-lighting-scene-col";
19028
19010
  this.viewToggleEl = this.buildViewToggle();
@@ -19031,7 +19013,7 @@ var LightingEditor = class _LightingEditor {
19031
19013
  this.sceneViewport.className = "aicut-lighting-scene-viewport";
19032
19014
  this.sceneViewport.setAttribute("data-testid", "aicut-lighting-scene");
19033
19015
  sceneCol.appendChild(this.sceneViewport);
19034
- this.body.appendChild(sceneCol);
19016
+ body.appendChild(sceneCol);
19035
19017
  this.controls = new LightingControls(this.locale, {
19036
19018
  onBrightnessChange: (level) => this.applyMutation({ brightness: level }),
19037
19019
  onColorChange: (hex) => this.applyMutation({ color: hex }),
@@ -19042,17 +19024,7 @@ var LightingEditor = class _LightingEditor {
19042
19024
  onRimToggle: (on) => this.applyMutation({ rim: on }),
19043
19025
  onReset: () => this.setConfig(DEFAULT_LIGHTING_CONFIG, "reset")
19044
19026
  });
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();
19027
+ body.appendChild(this.controls.root);
19056
19028
  this.scene = new LightingScene(this.sceneViewport, this.view);
19057
19029
  this.scene.setLightDirection(this.config.keyDirection);
19058
19030
  this.scene.setBrightness(this.config.brightness);
@@ -19105,42 +19077,6 @@ var LightingEditor = class _LightingEditor {
19105
19077
  getView() {
19106
19078
  return this.view;
19107
19079
  }
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
19080
  setTheme(theme) {
19145
19081
  applyTheme(this.root, theme);
19146
19082
  }
@@ -19151,10 +19087,6 @@ var LightingEditor = class _LightingEditor {
19151
19087
  };
19152
19088
  this.controls.setLocale(this.locale);
19153
19089
  this.syncViewToggle();
19154
- this.syncSmartLocale();
19155
- }
19156
- requestGenerate() {
19157
- this.opts.onGenerate?.(this.getConfig());
19158
19090
  }
19159
19091
  destroy() {
19160
19092
  if (this.destroyed) return;
@@ -19163,8 +19095,6 @@ var LightingEditor = class _LightingEditor {
19163
19095
  this.scene.destroy();
19164
19096
  this.root.innerHTML = "";
19165
19097
  this.root.classList.remove("aicut-root", "aicut-lighting-editor");
19166
- this.root.removeAttribute("data-smart-enabled");
19167
- this.root.removeAttribute("data-smart-open");
19168
19098
  }
19169
19099
  // ---- Internal ------------------------------------------------------
19170
19100
  applyMutation(partial) {
@@ -19214,86 +19144,6 @@ var LightingEditor = class _LightingEditor {
19214
19144
  if (v === "front") btn.textContent = this.locale.lightingViewFront;
19215
19145
  }
19216
19146
  }
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
19147
  };
19298
19148
  /*! Bundled license information:
19299
19149