@aicut/react 0.1.1 → 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.
package/README.md CHANGED
@@ -145,6 +145,48 @@ import { VideoEditor, localeZh } from "@aicut/react";
145
145
 
146
146
  `locale` is reactive too — runtime swap re-titles the toolbar and re-paints canvas labels in place.
147
147
 
148
+ ## `<LightingEditor>` (opt-in sub-entry)
149
+
150
+ A 3D lighting director for AI relighting flows — separate component that doesn't pull three.js into the rest of your bundle.
151
+
152
+ ```tsx
153
+ import { useRef } from "react";
154
+ import {
155
+ LightingEditor,
156
+ type LightingEditorApi,
157
+ type LightingConfig,
158
+ } from "@aicut/react/lighting";
159
+ import "@aicut/core/styles.css";
160
+
161
+ function Relight() {
162
+ const apiRef = useRef<LightingEditorApi | null>(null);
163
+ return (
164
+ <LightingEditor
165
+ apiRef={apiRef}
166
+ subjectImageUrl="/frames/subject.jpg"
167
+ smartEnabled
168
+ smartPanel={
169
+ <>
170
+ <textarea placeholder="Describe the mood…" />
171
+ <button onClick={() => apiRef.current?.requestGenerate()}>
172
+ Generate
173
+ </button>
174
+ </>
175
+ }
176
+ onChange={(cfg: LightingConfig) => console.log(cfg)}
177
+ onGenerate={(cfg) =>
178
+ fetch("/relight", {
179
+ method: "POST",
180
+ body: JSON.stringify(cfg),
181
+ })
182
+ }
183
+ />
184
+ );
185
+ }
186
+ ```
187
+
188
+ Props: `subjectImageUrl`, `defaultConfig`, `defaultView`, `theme`, `locale`, `smartEnabled`, `smartOpen`, `smartPanel`, `onChange`, `onGenerate`, `onSmartOpenChange`. The host's `smartPanel` is portaled into the editor's slot; the library renders the × close button + a "Smart mode" header pill to re-open it.
189
+
148
190
  ## Standalone `<Timeline>`
149
191
 
150
192
  Use the canvas timeline without the rest of the editor — frame-pickers, thumbnail strips, read-only previews.
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/lighting.ts
21
+ var lighting_exports = {};
22
+ __export(lighting_exports, {
23
+ DEFAULT_LIGHTING_CONFIG: () => import_lighting2.DEFAULT_LIGHTING_CONFIG,
24
+ LightingEditor: () => LightingEditor,
25
+ PRESET_DIRECTIONS: () => import_lighting2.PRESET_DIRECTIONS,
26
+ lightingLocaleEn: () => import_lighting2.lightingLocaleEn,
27
+ lightingLocaleZh: () => import_lighting2.lightingLocaleZh,
28
+ mergeLightingLocale: () => import_lighting2.mergeLightingLocale,
29
+ snapToPreset: () => import_lighting2.snapToPreset
30
+ });
31
+ module.exports = __toCommonJS(lighting_exports);
32
+
33
+ // src/LightingEditor.tsx
34
+ var import_react = require("react");
35
+ var import_lighting = require("@aicut/core/lighting");
36
+ var import_jsx_runtime = require("react/jsx-runtime");
37
+ function LightingEditor(props) {
38
+ const hostRef = (0, import_react.useRef)(null);
39
+ const editorRef = (0, import_react.useRef)(null);
40
+ const [ready, setReady] = (0, import_react.useState)(false);
41
+ const cbRef = (0, import_react.useRef)(props);
42
+ cbRef.current = props;
43
+ (0, import_react.useEffect)(() => {
44
+ const host = hostRef.current;
45
+ if (!host) return;
46
+ const editor = import_lighting.LightingEditor.create({
47
+ container: host,
48
+ subjectImageUrl: cbRef.current.subjectImageUrl,
49
+ config: cbRef.current.defaultConfig,
50
+ view: cbRef.current.defaultView,
51
+ theme: cbRef.current.theme,
52
+ locale: cbRef.current.locale,
53
+ onChange: (cfg) => cbRef.current.onChange?.(cfg)
54
+ });
55
+ editorRef.current = editor;
56
+ setReady(true);
57
+ return () => {
58
+ editor.destroy();
59
+ editorRef.current = null;
60
+ setReady(false);
61
+ };
62
+ }, []);
63
+ (0, import_react.useEffect)(() => {
64
+ if (props.theme) editorRef.current?.setTheme(props.theme);
65
+ }, [props.theme]);
66
+ (0, import_react.useEffect)(() => {
67
+ editorRef.current?.setLocale(props.locale ?? {});
68
+ }, [props.locale]);
69
+ (0, import_react.useEffect)(() => {
70
+ if (props.subjectImageUrl)
71
+ editorRef.current?.setSubjectImage(props.subjectImageUrl);
72
+ }, [props.subjectImageUrl]);
73
+ (0, import_react.useImperativeHandle)(
74
+ props.apiRef,
75
+ () => {
76
+ const ed = editorRef.current;
77
+ if (!ed) return null;
78
+ return {
79
+ setConfig: (p) => ed.setConfig(p),
80
+ getConfig: () => ed.getConfig(),
81
+ setSubjectImage: (url) => ed.setSubjectImage(url),
82
+ setView: (v) => ed.setView(v),
83
+ getView: () => ed.getView()
84
+ };
85
+ },
86
+ [ready]
87
+ );
88
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
89
+ "div",
90
+ {
91
+ ref: hostRef,
92
+ className: props.className,
93
+ style: props.style,
94
+ "data-aicut-lighting-host": ""
95
+ }
96
+ );
97
+ }
98
+
99
+ // src/lighting.ts
100
+ var import_lighting2 = require("@aicut/core/lighting");
101
+ // Annotate the CommonJS export names for ESM import in node:
102
+ 0 && (module.exports = {
103
+ DEFAULT_LIGHTING_CONFIG,
104
+ LightingEditor,
105
+ PRESET_DIRECTIONS,
106
+ lightingLocaleEn,
107
+ lightingLocaleZh,
108
+ mergeLightingLocale,
109
+ snapToPreset
110
+ });
111
+ //# sourceMappingURL=lighting.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lighting.ts","../src/LightingEditor.tsx"],"sourcesContent":["/**\n * @aicut/react/lighting — separate entry that pulls three.js. Users\n * who never import this path don't pay the three.js bundle cost.\n */\nexport { LightingEditor } from \"./LightingEditor.js\";\nexport type {\n LightingEditorProps,\n LightingEditorApi,\n} from \"./LightingEditor.js\";\n\n// Re-export the data + locale exports from the core sub-entry so\n// hosts only need a single import line for everything lighting-related.\nexport {\n DEFAULT_LIGHTING_CONFIG,\n PRESET_DIRECTIONS,\n lightingLocaleEn,\n lightingLocaleZh,\n mergeLightingLocale,\n snapToPreset,\n} from \"@aicut/core/lighting\";\nexport type {\n KeyPreset,\n LightingConfig,\n LightingEditorOptions,\n LightingLocale,\n LightingView,\n} from \"@aicut/core/lighting\";\n","import {\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type Ref,\n} from \"react\";\nimport {\n LightingEditor as CoreLightingEditor,\n type LightingConfig,\n type LightingEditorOptions,\n type LightingView,\n} from \"@aicut/core/lighting\";\nimport type { Theme } from \"@aicut/core\";\n\nexport interface LightingEditorApi {\n setConfig(partial: Partial<LightingConfig>): void;\n getConfig(): LightingConfig;\n setSubjectImage(url: string): void;\n setView(v: LightingView): void;\n getView(): LightingView;\n}\n\nexport interface LightingEditorProps {\n /** Initial subject image (URL or data URI). Reactive. */\n subjectImageUrl?: string;\n /** Initial config. */\n defaultConfig?: Partial<LightingConfig>;\n /** Initial view. Default `\"perspective\"`. */\n defaultView?: LightingView;\n /** Theme — reactive (calls editor.setTheme). */\n theme?: Theme;\n /** Locale partial — reactive (calls editor.setLocale). */\n locale?: LightingEditorOptions[\"locale\"];\n\n className?: string;\n style?: CSSProperties;\n apiRef?: Ref<LightingEditorApi | null>;\n\n onChange?: (cfg: LightingConfig) => void;\n}\n\n/**\n * React shell for the 3D lighting picker. Renders scene + controls;\n * nothing else. Host code lays out their own surrounding UI (smart\n * mode panel, generate button, etc.) alongside this component in\n * whatever flex/grid the host prefers.\n */\nexport function LightingEditor(props: LightingEditorProps) {\n const hostRef = useRef<HTMLDivElement | null>(null);\n const editorRef = useRef<CoreLightingEditor | null>(null);\n // Triggers a re-render the moment the editor is created, so the\n // useImperativeHandle factory below can return the real instance\n // instead of locking at null forever (same trick as VideoEditor).\n const [ready, setReady] = useState(false);\n\n const cbRef = useRef(props);\n cbRef.current = props;\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const editor = CoreLightingEditor.create({\n container: host,\n subjectImageUrl: cbRef.current.subjectImageUrl,\n config: cbRef.current.defaultConfig,\n view: cbRef.current.defaultView,\n theme: cbRef.current.theme,\n locale: cbRef.current.locale,\n onChange: (cfg) => cbRef.current.onChange?.(cfg),\n });\n editorRef.current = editor;\n setReady(true);\n return () => {\n editor.destroy();\n editorRef.current = null;\n setReady(false);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (props.theme) editorRef.current?.setTheme(props.theme);\n }, [props.theme]);\n useEffect(() => {\n // Always push — `undefined` is the \"reset to English defaults\"\n // signal. Without this, toggling ZH→EN in the host kept ZH labels.\n editorRef.current?.setLocale(props.locale ?? {});\n }, [props.locale]);\n useEffect(() => {\n if (props.subjectImageUrl)\n editorRef.current?.setSubjectImage(props.subjectImageUrl);\n }, [props.subjectImageUrl]);\n\n useImperativeHandle<LightingEditorApi | null, LightingEditorApi | null>(\n props.apiRef,\n () => {\n const ed = editorRef.current;\n if (!ed) return null;\n return {\n setConfig: (p) => ed.setConfig(p),\n getConfig: () => ed.getConfig(),\n setSubjectImage: (url) => ed.setSubjectImage(url),\n setView: (v) => ed.setView(v),\n getView: () => ed.getView(),\n };\n },\n [ready],\n );\n\n return (\n <div\n ref={hostRef}\n className={props.className}\n style={props.style}\n data-aicut-lighting-host=\"\"\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAOO;AACP,sBAKO;AAmGH;AA/DG,SAAS,eAAe,OAA4B;AACzD,QAAM,cAAU,qBAA8B,IAAI;AAClD,QAAM,gBAAY,qBAAkC,IAAI;AAIxD,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAS,KAAK;AAExC,QAAM,YAAQ,qBAAO,KAAK;AAC1B,QAAM,UAAU;AAEhB,8BAAU,MAAM;AACd,UAAM,OAAO,QAAQ;AACrB,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,gBAAAA,eAAmB,OAAO;AAAA,MACvC,WAAW;AAAA,MACX,iBAAiB,MAAM,QAAQ;AAAA,MAC/B,QAAQ,MAAM,QAAQ;AAAA,MACtB,MAAM,MAAM,QAAQ;AAAA,MACpB,OAAO,MAAM,QAAQ;AAAA,MACrB,QAAQ,MAAM,QAAQ;AAAA,MACtB,UAAU,CAAC,QAAQ,MAAM,QAAQ,WAAW,GAAG;AAAA,IACjD,CAAC;AACD,cAAU,UAAU;AACpB,aAAS,IAAI;AACb,WAAO,MAAM;AACX,aAAO,QAAQ;AACf,gBAAU,UAAU;AACpB,eAAS,KAAK;AAAA,IAChB;AAAA,EAEF,GAAG,CAAC,CAAC;AAEL,8BAAU,MAAM;AACd,QAAI,MAAM,MAAO,WAAU,SAAS,SAAS,MAAM,KAAK;AAAA,EAC1D,GAAG,CAAC,MAAM,KAAK,CAAC;AAChB,8BAAU,MAAM;AAGd,cAAU,SAAS,UAAU,MAAM,UAAU,CAAC,CAAC;AAAA,EACjD,GAAG,CAAC,MAAM,MAAM,CAAC;AACjB,8BAAU,MAAM;AACd,QAAI,MAAM;AACR,gBAAU,SAAS,gBAAgB,MAAM,eAAe;AAAA,EAC5D,GAAG,CAAC,MAAM,eAAe,CAAC;AAE1B;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AACJ,YAAM,KAAK,UAAU;AACrB,UAAI,CAAC,GAAI,QAAO;AAChB,aAAO;AAAA,QACL,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC;AAAA,QAChC,WAAW,MAAM,GAAG,UAAU;AAAA,QAC9B,iBAAiB,CAAC,QAAQ,GAAG,gBAAgB,GAAG;AAAA,QAChD,SAAS,CAAC,MAAM,GAAG,QAAQ,CAAC;AAAA,QAC5B,SAAS,MAAM,GAAG,QAAQ;AAAA,MAC5B;AAAA,IACF;AAAA,IACA,CAAC,KAAK;AAAA,EACR;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAW,MAAM;AAAA,MACjB,OAAO,MAAM;AAAA,MACb,4BAAyB;AAAA;AAAA,EAC3B;AAEJ;;;AD3GA,IAAAC,mBAOO;","names":["CoreLightingEditor","import_lighting"]}
@@ -0,0 +1,38 @@
1
+ import * as react from 'react';
2
+ import { CSSProperties, Ref } from 'react';
3
+ import { LightingConfig, LightingView, LightingEditorOptions } from '@aicut/core/lighting';
4
+ export { DEFAULT_LIGHTING_CONFIG, KeyPreset, LightingConfig, LightingEditorOptions, LightingLocale, LightingView, PRESET_DIRECTIONS, lightingLocaleEn, lightingLocaleZh, mergeLightingLocale, snapToPreset } from '@aicut/core/lighting';
5
+ import { Theme } from '@aicut/core';
6
+
7
+ interface LightingEditorApi {
8
+ setConfig(partial: Partial<LightingConfig>): void;
9
+ getConfig(): LightingConfig;
10
+ setSubjectImage(url: string): void;
11
+ setView(v: LightingView): void;
12
+ getView(): LightingView;
13
+ }
14
+ interface LightingEditorProps {
15
+ /** Initial subject image (URL or data URI). Reactive. */
16
+ subjectImageUrl?: string;
17
+ /** Initial config. */
18
+ defaultConfig?: Partial<LightingConfig>;
19
+ /** Initial view. Default `"perspective"`. */
20
+ defaultView?: LightingView;
21
+ /** Theme — reactive (calls editor.setTheme). */
22
+ theme?: Theme;
23
+ /** Locale partial — reactive (calls editor.setLocale). */
24
+ locale?: LightingEditorOptions["locale"];
25
+ className?: string;
26
+ style?: CSSProperties;
27
+ apiRef?: Ref<LightingEditorApi | null>;
28
+ onChange?: (cfg: LightingConfig) => void;
29
+ }
30
+ /**
31
+ * React shell for the 3D lighting picker. Renders scene + controls;
32
+ * nothing else. Host code lays out their own surrounding UI (smart
33
+ * mode panel, generate button, etc.) alongside this component in
34
+ * whatever flex/grid the host prefers.
35
+ */
36
+ declare function LightingEditor(props: LightingEditorProps): react.JSX.Element;
37
+
38
+ export { LightingEditor, type LightingEditorApi, type LightingEditorProps };
@@ -0,0 +1,38 @@
1
+ import * as react from 'react';
2
+ import { CSSProperties, Ref } from 'react';
3
+ import { LightingConfig, LightingView, LightingEditorOptions } from '@aicut/core/lighting';
4
+ export { DEFAULT_LIGHTING_CONFIG, KeyPreset, LightingConfig, LightingEditorOptions, LightingLocale, LightingView, PRESET_DIRECTIONS, lightingLocaleEn, lightingLocaleZh, mergeLightingLocale, snapToPreset } from '@aicut/core/lighting';
5
+ import { Theme } from '@aicut/core';
6
+
7
+ interface LightingEditorApi {
8
+ setConfig(partial: Partial<LightingConfig>): void;
9
+ getConfig(): LightingConfig;
10
+ setSubjectImage(url: string): void;
11
+ setView(v: LightingView): void;
12
+ getView(): LightingView;
13
+ }
14
+ interface LightingEditorProps {
15
+ /** Initial subject image (URL or data URI). Reactive. */
16
+ subjectImageUrl?: string;
17
+ /** Initial config. */
18
+ defaultConfig?: Partial<LightingConfig>;
19
+ /** Initial view. Default `"perspective"`. */
20
+ defaultView?: LightingView;
21
+ /** Theme — reactive (calls editor.setTheme). */
22
+ theme?: Theme;
23
+ /** Locale partial — reactive (calls editor.setLocale). */
24
+ locale?: LightingEditorOptions["locale"];
25
+ className?: string;
26
+ style?: CSSProperties;
27
+ apiRef?: Ref<LightingEditorApi | null>;
28
+ onChange?: (cfg: LightingConfig) => void;
29
+ }
30
+ /**
31
+ * React shell for the 3D lighting picker. Renders scene + controls;
32
+ * nothing else. Host code lays out their own surrounding UI (smart
33
+ * mode panel, generate button, etc.) alongside this component in
34
+ * whatever flex/grid the host prefers.
35
+ */
36
+ declare function LightingEditor(props: LightingEditorProps): react.JSX.Element;
37
+
38
+ export { LightingEditor, type LightingEditorApi, type LightingEditorProps };
@@ -0,0 +1,92 @@
1
+ // src/LightingEditor.tsx
2
+ import {
3
+ useEffect,
4
+ useImperativeHandle,
5
+ useRef,
6
+ useState
7
+ } from "react";
8
+ import {
9
+ LightingEditor as CoreLightingEditor
10
+ } from "@aicut/core/lighting";
11
+ import { jsx } from "react/jsx-runtime";
12
+ function LightingEditor(props) {
13
+ const hostRef = useRef(null);
14
+ const editorRef = useRef(null);
15
+ const [ready, setReady] = useState(false);
16
+ const cbRef = useRef(props);
17
+ cbRef.current = props;
18
+ useEffect(() => {
19
+ const host = hostRef.current;
20
+ if (!host) return;
21
+ const editor = CoreLightingEditor.create({
22
+ container: host,
23
+ subjectImageUrl: cbRef.current.subjectImageUrl,
24
+ config: cbRef.current.defaultConfig,
25
+ view: cbRef.current.defaultView,
26
+ theme: cbRef.current.theme,
27
+ locale: cbRef.current.locale,
28
+ onChange: (cfg) => cbRef.current.onChange?.(cfg)
29
+ });
30
+ editorRef.current = editor;
31
+ setReady(true);
32
+ return () => {
33
+ editor.destroy();
34
+ editorRef.current = null;
35
+ setReady(false);
36
+ };
37
+ }, []);
38
+ useEffect(() => {
39
+ if (props.theme) editorRef.current?.setTheme(props.theme);
40
+ }, [props.theme]);
41
+ useEffect(() => {
42
+ editorRef.current?.setLocale(props.locale ?? {});
43
+ }, [props.locale]);
44
+ useEffect(() => {
45
+ if (props.subjectImageUrl)
46
+ editorRef.current?.setSubjectImage(props.subjectImageUrl);
47
+ }, [props.subjectImageUrl]);
48
+ useImperativeHandle(
49
+ props.apiRef,
50
+ () => {
51
+ const ed = editorRef.current;
52
+ if (!ed) return null;
53
+ return {
54
+ setConfig: (p) => ed.setConfig(p),
55
+ getConfig: () => ed.getConfig(),
56
+ setSubjectImage: (url) => ed.setSubjectImage(url),
57
+ setView: (v) => ed.setView(v),
58
+ getView: () => ed.getView()
59
+ };
60
+ },
61
+ [ready]
62
+ );
63
+ return /* @__PURE__ */ jsx(
64
+ "div",
65
+ {
66
+ ref: hostRef,
67
+ className: props.className,
68
+ style: props.style,
69
+ "data-aicut-lighting-host": ""
70
+ }
71
+ );
72
+ }
73
+
74
+ // src/lighting.ts
75
+ import {
76
+ DEFAULT_LIGHTING_CONFIG,
77
+ PRESET_DIRECTIONS,
78
+ lightingLocaleEn,
79
+ lightingLocaleZh,
80
+ mergeLightingLocale,
81
+ snapToPreset
82
+ } from "@aicut/core/lighting";
83
+ export {
84
+ DEFAULT_LIGHTING_CONFIG,
85
+ LightingEditor,
86
+ PRESET_DIRECTIONS,
87
+ lightingLocaleEn,
88
+ lightingLocaleZh,
89
+ mergeLightingLocale,
90
+ snapToPreset
91
+ };
92
+ //# sourceMappingURL=lighting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/LightingEditor.tsx","../src/lighting.ts"],"sourcesContent":["import {\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type Ref,\n} from \"react\";\nimport {\n LightingEditor as CoreLightingEditor,\n type LightingConfig,\n type LightingEditorOptions,\n type LightingView,\n} from \"@aicut/core/lighting\";\nimport type { Theme } from \"@aicut/core\";\n\nexport interface LightingEditorApi {\n setConfig(partial: Partial<LightingConfig>): void;\n getConfig(): LightingConfig;\n setSubjectImage(url: string): void;\n setView(v: LightingView): void;\n getView(): LightingView;\n}\n\nexport interface LightingEditorProps {\n /** Initial subject image (URL or data URI). Reactive. */\n subjectImageUrl?: string;\n /** Initial config. */\n defaultConfig?: Partial<LightingConfig>;\n /** Initial view. Default `\"perspective\"`. */\n defaultView?: LightingView;\n /** Theme — reactive (calls editor.setTheme). */\n theme?: Theme;\n /** Locale partial — reactive (calls editor.setLocale). */\n locale?: LightingEditorOptions[\"locale\"];\n\n className?: string;\n style?: CSSProperties;\n apiRef?: Ref<LightingEditorApi | null>;\n\n onChange?: (cfg: LightingConfig) => void;\n}\n\n/**\n * React shell for the 3D lighting picker. Renders scene + controls;\n * nothing else. Host code lays out their own surrounding UI (smart\n * mode panel, generate button, etc.) alongside this component in\n * whatever flex/grid the host prefers.\n */\nexport function LightingEditor(props: LightingEditorProps) {\n const hostRef = useRef<HTMLDivElement | null>(null);\n const editorRef = useRef<CoreLightingEditor | null>(null);\n // Triggers a re-render the moment the editor is created, so the\n // useImperativeHandle factory below can return the real instance\n // instead of locking at null forever (same trick as VideoEditor).\n const [ready, setReady] = useState(false);\n\n const cbRef = useRef(props);\n cbRef.current = props;\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const editor = CoreLightingEditor.create({\n container: host,\n subjectImageUrl: cbRef.current.subjectImageUrl,\n config: cbRef.current.defaultConfig,\n view: cbRef.current.defaultView,\n theme: cbRef.current.theme,\n locale: cbRef.current.locale,\n onChange: (cfg) => cbRef.current.onChange?.(cfg),\n });\n editorRef.current = editor;\n setReady(true);\n return () => {\n editor.destroy();\n editorRef.current = null;\n setReady(false);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (props.theme) editorRef.current?.setTheme(props.theme);\n }, [props.theme]);\n useEffect(() => {\n // Always push — `undefined` is the \"reset to English defaults\"\n // signal. Without this, toggling ZH→EN in the host kept ZH labels.\n editorRef.current?.setLocale(props.locale ?? {});\n }, [props.locale]);\n useEffect(() => {\n if (props.subjectImageUrl)\n editorRef.current?.setSubjectImage(props.subjectImageUrl);\n }, [props.subjectImageUrl]);\n\n useImperativeHandle<LightingEditorApi | null, LightingEditorApi | null>(\n props.apiRef,\n () => {\n const ed = editorRef.current;\n if (!ed) return null;\n return {\n setConfig: (p) => ed.setConfig(p),\n getConfig: () => ed.getConfig(),\n setSubjectImage: (url) => ed.setSubjectImage(url),\n setView: (v) => ed.setView(v),\n getView: () => ed.getView(),\n };\n },\n [ready],\n );\n\n return (\n <div\n ref={hostRef}\n className={props.className}\n style={props.style}\n data-aicut-lighting-host=\"\"\n />\n );\n}\n","/**\n * @aicut/react/lighting — separate entry that pulls three.js. Users\n * who never import this path don't pay the three.js bundle cost.\n */\nexport { LightingEditor } from \"./LightingEditor.js\";\nexport type {\n LightingEditorProps,\n LightingEditorApi,\n} from \"./LightingEditor.js\";\n\n// Re-export the data + locale exports from the core sub-entry so\n// hosts only need a single import line for everything lighting-related.\nexport {\n DEFAULT_LIGHTING_CONFIG,\n PRESET_DIRECTIONS,\n lightingLocaleEn,\n lightingLocaleZh,\n mergeLightingLocale,\n snapToPreset,\n} from \"@aicut/core/lighting\";\nexport type {\n KeyPreset,\n LightingConfig,\n LightingEditorOptions,\n LightingLocale,\n LightingView,\n} from \"@aicut/core/lighting\";\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE,kBAAkB;AAAA,OAIb;AAmGH;AA/DG,SAAS,eAAe,OAA4B;AACzD,QAAM,UAAU,OAA8B,IAAI;AAClD,QAAM,YAAY,OAAkC,IAAI;AAIxD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AAExC,QAAM,QAAQ,OAAO,KAAK;AAC1B,QAAM,UAAU;AAEhB,YAAU,MAAM;AACd,UAAM,OAAO,QAAQ;AACrB,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,mBAAmB,OAAO;AAAA,MACvC,WAAW;AAAA,MACX,iBAAiB,MAAM,QAAQ;AAAA,MAC/B,QAAQ,MAAM,QAAQ;AAAA,MACtB,MAAM,MAAM,QAAQ;AAAA,MACpB,OAAO,MAAM,QAAQ;AAAA,MACrB,QAAQ,MAAM,QAAQ;AAAA,MACtB,UAAU,CAAC,QAAQ,MAAM,QAAQ,WAAW,GAAG;AAAA,IACjD,CAAC;AACD,cAAU,UAAU;AACpB,aAAS,IAAI;AACb,WAAO,MAAM;AACX,aAAO,QAAQ;AACf,gBAAU,UAAU;AACpB,eAAS,KAAK;AAAA,IAChB;AAAA,EAEF,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,QAAI,MAAM,MAAO,WAAU,SAAS,SAAS,MAAM,KAAK;AAAA,EAC1D,GAAG,CAAC,MAAM,KAAK,CAAC;AAChB,YAAU,MAAM;AAGd,cAAU,SAAS,UAAU,MAAM,UAAU,CAAC,CAAC;AAAA,EACjD,GAAG,CAAC,MAAM,MAAM,CAAC;AACjB,YAAU,MAAM;AACd,QAAI,MAAM;AACR,gBAAU,SAAS,gBAAgB,MAAM,eAAe;AAAA,EAC5D,GAAG,CAAC,MAAM,eAAe,CAAC;AAE1B;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AACJ,YAAM,KAAK,UAAU;AACrB,UAAI,CAAC,GAAI,QAAO;AAChB,aAAO;AAAA,QACL,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC;AAAA,QAChC,WAAW,MAAM,GAAG,UAAU;AAAA,QAC9B,iBAAiB,CAAC,QAAQ,GAAG,gBAAgB,GAAG;AAAA,QAChD,SAAS,CAAC,MAAM,GAAG,QAAQ,CAAC;AAAA,QAC5B,SAAS,MAAM,GAAG,QAAQ;AAAA,MAC5B;AAAA,IACF;AAAA,IACA,CAAC,KAAK;AAAA,EACR;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAW,MAAM;AAAA,MACjB,OAAO,MAAM;AAAA,MACb,4BAAyB;AAAA;AAAA,EAC3B;AAEJ;;;AC3GA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aicut/react",
3
- "version": "0.1.1",
4
- "description": "React wrapper for the AiCut video editor — thin declarative shell over @aicut/core.",
3
+ "version": "0.3.0",
4
+ "description": "React wrapper for the AiCut video editor + lighting picker — thin declarative shells over @aicut/core.",
5
5
  "license": "MIT",
6
6
  "author": "ziqiang <ziqiangytu@gmail.com>",
7
7
  "homepage": "https://github.com/ziqiangai/AiCut#readme",
@@ -34,7 +34,9 @@
34
34
  "davinci",
35
35
  "imovie",
36
36
  "veed",
37
- "filmora"
37
+ "filmora",
38
+ "lighting",
39
+ "three.js"
38
40
  ],
39
41
  "type": "module",
40
42
  "main": "./dist/index.cjs",
@@ -45,6 +47,11 @@
45
47
  "types": "./dist/index.d.ts",
46
48
  "import": "./dist/index.js",
47
49
  "require": "./dist/index.cjs"
50
+ },
51
+ "./lighting": {
52
+ "types": "./dist/lighting.d.ts",
53
+ "import": "./dist/lighting.js",
54
+ "require": "./dist/lighting.cjs"
48
55
  }
49
56
  },
50
57
  "files": [
@@ -52,7 +59,7 @@
52
59
  "README.md"
53
60
  ],
54
61
  "dependencies": {
55
- "@aicut/core": "0.1.1"
62
+ "@aicut/core": "0.3.0"
56
63
  },
57
64
  "peerDependencies": {
58
65
  "react": "^18.0.0 || ^19.0.0",