@aicut/core 0.3.0 → 0.4.1

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/README.md CHANGED
@@ -144,7 +144,9 @@ editor.toolbarRight.appendChild(exportBtn);
144
144
 
145
145
  ## Lighting picker (opt-in sub-entry)
146
146
 
147
- A separate component for AI relighting workflows — drag a light dot around a 3D sphere wrapping a subject frame, control brightness / color / direction. Three.js is bundled only on this sub-entry, so consumers of the video editor pay zero bytes for it.
147
+ A separate component for AI-relighting workflows — drag a light dot around a 3D sphere wrapping a subject frame, control brightness / color / direction. Three.js is bundled only on this sub-entry, so consumers of the video editor pay zero bytes for it.
148
+
149
+ The library renders **only the picker** (scene + controls). Smart-mode UI (prompt textarea, preset thumbnails, Generate button, close handling) is host code laid out beside `<LightingEditor>`.
148
150
 
149
151
  ```ts
150
152
  import { LightingEditor } from "@aicut/core/lighting";
@@ -153,23 +155,31 @@ import "@aicut/core/styles.css";
153
155
  const ed = LightingEditor.create({
154
156
  container: document.getElementById("light")!,
155
157
  subjectImageUrl: "/frames/subject.jpg",
156
- smartEnabled: true, // default; false → no slot column at all
157
- smartOpen: true, // default; user can toggle via × / header pill
158
158
  onChange: (cfg) => console.log(cfg),
159
- onGenerate: (cfg) => fetch("/relight", { method: "POST", body: JSON.stringify(cfg) }),
160
159
  });
161
160
 
162
- // Host appends UI into the smart slot (prompt textarea, presets, generate btn, …).
163
- ed.smartSlot.appendChild(myAiUI);
164
-
165
- // Runtime control:
166
- ed.setSmartOpen(false);
167
- ed.setSmartEnabled(false);
161
+ // Runtime control
168
162
  ed.setView("front");
169
163
  ed.setConfig({ brightness: 0.8, color: "#ffaa3a" });
164
+ ed.setSubjectImage("/frames/another-subject.jpg");
165
+ ed.reset(); // restore safe defaults
166
+
167
+ // Footer slot — the only DOM region the library leaves for host action
168
+ // buttons (Reset, Generate, save-preset, etc.). Library renders nothing
169
+ // into it; host appends whatever it wants:
170
+ const resetBtn = document.createElement("button");
171
+ resetBtn.textContent = "Reset";
172
+ resetBtn.onclick = () => ed.reset();
173
+ ed.controlsFooter.appendChild(resetBtn);
174
+
175
+ // Host snapshot for "Generate" — call from your own button
176
+ function onGenerate() {
177
+ const cfg = ed.getConfig();
178
+ fetch("/relight", { method: "POST", body: JSON.stringify(cfg) });
179
+ }
170
180
  ```
171
181
 
172
- Locale extension `LightingLocale` (separate from the video editor's `Locale`) is also exported with `lightingLocaleEn` / `lightingLocaleZh`.
182
+ Locale extension `LightingLocale` (separate from the video editor's `Locale`) is exported with `lightingLocaleEn` / `lightingLocaleZh`.
173
183
 
174
184
  ## Standalone Timeline
175
185
 
@@ -90,6 +90,13 @@ var LightingControls = class {
90
90
  /** Exposed so the editor can append host-level chrome (e.g. the
91
91
  * Smart Mode toggle) without LightingControls knowing about it. */
92
92
  headerSlot;
93
+ /**
94
+ * Footer slot — sits where the built-in Reset used to live. Host
95
+ * appends any action buttons (Reset, Generate, Save preset, etc.)
96
+ * via the React wrapper's `controlsFooter` prop / Vue's
97
+ * `<slot name="controlsFooter">`. Library renders nothing here.
98
+ */
99
+ footerSlot;
93
100
  brightnessInput;
94
101
  colorInput;
95
102
  dirButtons;
@@ -102,7 +109,6 @@ var LightingControls = class {
102
109
  colorLabelEl;
103
110
  keyLabelEl;
104
111
  rimLabelEl;
105
- resetBtn;
106
112
  locale;
107
113
  lastConfig = null;
108
114
  constructor(locale, cb) {
@@ -192,15 +198,12 @@ var LightingControls = class {
192
198
  });
193
199
  rimSection.appendChild(this.rimToggle);
194
200
  this.root.appendChild(rimSection);
195
- const footer = mkDiv("aicut-lighting-section aicut-lighting-section-row");
196
- this.resetBtn = document.createElement("button");
197
- this.resetBtn.type = "button";
198
- this.resetBtn.className = "aicut-lighting-reset";
199
- this.resetBtn.textContent = locale.lightingResetParams;
200
- this.resetBtn.setAttribute("data-testid", "aicut-lighting-reset");
201
- this.resetBtn.addEventListener("click", () => cb.onReset());
202
- footer.appendChild(this.resetBtn);
203
- this.root.appendChild(footer);
201
+ this.footerSlot = mkDiv("aicut-lighting-controls-footer");
202
+ this.footerSlot.setAttribute(
203
+ "data-testid",
204
+ "aicut-lighting-controls-footer"
205
+ );
206
+ this.root.appendChild(this.footerSlot);
204
207
  }
205
208
  /** Idempotent — mirror the given config into all visible controls. */
206
209
  render(cfg) {
@@ -229,7 +232,6 @@ var LightingControls = class {
229
232
  this.colorLabelEl.textContent = locale.lightingColor;
230
233
  this.keyLabelEl.textContent = locale.lightingKeyTitle;
231
234
  this.rimLabelEl.textContent = locale.lightingRim;
232
- this.resetBtn.textContent = locale.lightingResetParams;
233
235
  const dirLabels = {
234
236
  left: "lightingDirLeft",
235
237
  right: "lightingDirRight",
@@ -265,7 +267,6 @@ var lightingLocaleEn = {
265
267
  lightingRim: "Rim light",
266
268
  lightingViewPerspective: "Perspective",
267
269
  lightingViewFront: "Front",
268
- lightingResetParams: "Reset",
269
270
  lightingDirLeft: "Left",
270
271
  lightingDirRight: "Right",
271
272
  lightingDirTop: "Top",
@@ -282,7 +283,6 @@ var lightingLocaleZh = {
282
283
  lightingRim: "\u8F6E\u5ED3\u5149",
283
284
  lightingViewPerspective: "\u900F\u89C6",
284
285
  lightingViewFront: "\u6B63\u9762",
285
- lightingResetParams: "\u91CD\u7F6E\u53C2\u6570",
286
286
  lightingDirLeft: "\u5DE6\u4FA7",
287
287
  lightingDirRight: "\u53F3\u4FA7",
288
288
  lightingDirTop: "\u9876\u90E8",
@@ -19041,6 +19041,10 @@ var LightingEditor = class _LightingEditor {
19041
19041
  controls;
19042
19042
  sceneViewport;
19043
19043
  viewToggleEl;
19044
+ /** Footer slot in the controls column. Host appends Reset/Generate/
19045
+ * preset-save/etc. buttons here. The library renders nothing into
19046
+ * it — it's the same convention as the video editor's toolbar slots. */
19047
+ controlsFooter;
19044
19048
  resizeObs = null;
19045
19049
  destroyed = false;
19046
19050
  static create(opts) {
@@ -19078,10 +19082,10 @@ var LightingEditor = class _LightingEditor {
19078
19082
  keyDirection: PRESET_DIRECTIONS[preset],
19079
19083
  keyPreset: preset
19080
19084
  }),
19081
- onRimToggle: (on) => this.applyMutation({ rim: on }),
19082
- onReset: () => this.setConfig(DEFAULT_LIGHTING_CONFIG, "reset")
19085
+ onRimToggle: (on) => this.applyMutation({ rim: on })
19083
19086
  });
19084
19087
  body.appendChild(this.controls.root);
19088
+ this.controlsFooter = this.controls.footerSlot;
19085
19089
  this.scene = new LightingScene(this.sceneViewport, this.view);
19086
19090
  this.scene.setLightDirection(this.config.keyDirection);
19087
19091
  this.scene.setBrightness(this.config.brightness);
@@ -19125,6 +19129,11 @@ var LightingEditor = class _LightingEditor {
19125
19129
  this.opts.subjectImageUrl = url;
19126
19130
  this.scene.setSubjectImage(url);
19127
19131
  }
19132
+ /** Restore config to the safe defaults. Convenience for host's
19133
+ * "Reset" button — equivalent to `setConfig(DEFAULT_LIGHTING_CONFIG)`. */
19134
+ reset() {
19135
+ this.setConfig(DEFAULT_LIGHTING_CONFIG, "reset");
19136
+ }
19128
19137
  setView(v) {
19129
19138
  if (v === this.view) return;
19130
19139
  this.view = v;