@pictor-sdk/ui 0.1.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/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/index.d.mts +833 -0
- package/dist/index.d.ts +833 -0
- package/dist/index.js +4620 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4643 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +68 -0
- package/src/Editor.tsx +276 -0
- package/src/ToolPanelHost.tsx +98 -0
- package/src/components/Slider.tsx +172 -0
- package/src/components/StraightenRuler.tsx +57 -0
- package/src/components/ToolRail.tsx +58 -0
- package/src/components/TopBar.tsx +53 -0
- package/src/composer/TextComposer.tsx +540 -0
- package/src/composer/keyboardLayout.ts +130 -0
- package/src/composer/useTextSession.ts +230 -0
- package/src/gestures/CropGestureSurface.tsx +270 -0
- package/src/gestures/CropGrid.tsx +24 -0
- package/src/gestures/DrawingSurface.tsx +77 -0
- package/src/gestures/EditorGestures.tsx +97 -0
- package/src/gestures/InteractionGuides.tsx +161 -0
- package/src/gestures/LayerGestureSurface.tsx +462 -0
- package/src/gestures/StoryMediaGestureSurface.tsx +517 -0
- package/src/gestures/TiltShiftGestureSurface.tsx +189 -0
- package/src/gestures/controller.ts +152 -0
- package/src/gestures/drawController.ts +104 -0
- package/src/gestures/interactionState.tsx +81 -0
- package/src/gestures/layerGestureWorklet.ts +198 -0
- package/src/gestures/mediaGestureWorklet.ts +159 -0
- package/src/gestures/routing.ts +42 -0
- package/src/gestures/settleCoordinator.ts +61 -0
- package/src/gestures/transformOwnership.ts +91 -0
- package/src/hostCallbacks.tsx +62 -0
- package/src/index.ts +72 -0
- package/src/panels/AddPhotoPanel.tsx +101 -0
- package/src/panels/AdjustPanel.tsx +158 -0
- package/src/panels/ColorPanel.tsx +193 -0
- package/src/panels/CropPanel.tsx +185 -0
- package/src/panels/DrawPanel.tsx +106 -0
- package/src/panels/FilterStrip.tsx +153 -0
- package/src/panels/LayersPanel.tsx +85 -0
- package/src/panels/LayoutPanel.tsx +55 -0
- package/src/panels/LuxPanel.tsx +122 -0
- package/src/panels/MediaPanel.tsx +73 -0
- package/src/panels/PerspectivePanel.tsx +157 -0
- package/src/panels/StickerPanel.tsx +78 -0
- package/src/panels/TextPanel.tsx +177 -0
- package/src/panels/TiltShiftPanel.tsx +146 -0
- package/src/panels/addPhotoController.ts +196 -0
- package/src/panels/cropMath.ts +37 -0
- package/src/panels/layoutMath.ts +58 -0
- package/src/panels/useTargetImageLayer.ts +41 -0
- package/src/theme.ts +61 -0
- package/src/uiState.tsx +57 -0
package/src/theme.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Theming is one token object on context — no style props on individual
|
|
5
|
+
* components (ARCHITECTURE.md). Override any subset via <Editor theme={…}>.
|
|
6
|
+
*/
|
|
7
|
+
export interface EditorTheme {
|
|
8
|
+
colors: {
|
|
9
|
+
background: string
|
|
10
|
+
surface: string
|
|
11
|
+
text: string
|
|
12
|
+
textMuted: string
|
|
13
|
+
accent: string
|
|
14
|
+
danger: string
|
|
15
|
+
track: string
|
|
16
|
+
thumb: string
|
|
17
|
+
}
|
|
18
|
+
radii: { sm: number; md: number; lg: number }
|
|
19
|
+
spacing: { xs: number; sm: number; md: number; lg: number }
|
|
20
|
+
font: { size: number; sizeSm: number; weight: '400' | '500' | '600' | '700' }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** The bundled dark theme. Every value is overridable; see {@link mergeTheme}. */
|
|
24
|
+
export const defaultTheme: EditorTheme = {
|
|
25
|
+
colors: {
|
|
26
|
+
background: '#000000',
|
|
27
|
+
surface: '#121212',
|
|
28
|
+
text: '#ffffff',
|
|
29
|
+
textMuted: '#9a9a9a',
|
|
30
|
+
accent: '#3897f0',
|
|
31
|
+
danger: '#ed4956',
|
|
32
|
+
track: '#3a3a3a',
|
|
33
|
+
thumb: '#ffffff',
|
|
34
|
+
},
|
|
35
|
+
radii: { sm: 6, md: 10, lg: 16 },
|
|
36
|
+
spacing: { xs: 4, sm: 8, md: 14, lg: 22 },
|
|
37
|
+
font: { size: 15, sizeSm: 12, weight: '600' },
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** A theme override — any subset of any group, the rest falling back to the default. */
|
|
41
|
+
export type PartialTheme = {
|
|
42
|
+
[K in keyof EditorTheme]?: Partial<EditorTheme[K]>
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Apply an override onto the default theme, one group at a time. */
|
|
46
|
+
export function mergeTheme(overrides?: PartialTheme): EditorTheme {
|
|
47
|
+
if (!overrides) return defaultTheme
|
|
48
|
+
return {
|
|
49
|
+
colors: { ...defaultTheme.colors, ...overrides.colors },
|
|
50
|
+
radii: { ...defaultTheme.radii, ...overrides.radii },
|
|
51
|
+
spacing: { ...defaultTheme.spacing, ...overrides.spacing },
|
|
52
|
+
font: { ...defaultTheme.font, ...overrides.font },
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Carries the resolved theme. `<Editor>` provides it; components read it with {@link useTheme}. */
|
|
57
|
+
export const ThemeContext = createContext<EditorTheme>(defaultTheme)
|
|
58
|
+
/** The theme in effect. Defaults outside an `<Editor>` rather than throwing. */
|
|
59
|
+
export function useTheme(): EditorTheme {
|
|
60
|
+
return useContext(ThemeContext)
|
|
61
|
+
}
|
package/src/uiState.tsx
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React, { createContext, useCallback, useContext, useRef, useSyncExternalStore } from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A tiny shared key/value store for panel ↔ canvas coordination (brush
|
|
5
|
+
* config, sticker catalogs, eyedropper mode). Ephemeral — never touches the
|
|
6
|
+
* document or history.
|
|
7
|
+
*/
|
|
8
|
+
export interface UiStateStore {
|
|
9
|
+
get<T>(key: string, fallback: T): T
|
|
10
|
+
set(key: string, value: unknown): void
|
|
11
|
+
subscribe(listener: () => void): () => void
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** A scratch store for UI state that is neither document nor history. */
|
|
15
|
+
export function createUiStateStore(): UiStateStore {
|
|
16
|
+
const values = new Map<string, unknown>()
|
|
17
|
+
const listeners = new Set<() => void>()
|
|
18
|
+
return {
|
|
19
|
+
get: <T,>(key: string, fallback: T) =>
|
|
20
|
+
(values.has(key) ? (values.get(key) as T) : fallback),
|
|
21
|
+
set(key, value) {
|
|
22
|
+
values.set(key, value)
|
|
23
|
+
for (const l of [...listeners]) l()
|
|
24
|
+
},
|
|
25
|
+
subscribe(listener) {
|
|
26
|
+
listeners.add(listener)
|
|
27
|
+
return () => listeners.delete(listener)
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const UiStateContext = createContext<UiStateStore | null>(null)
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Holds ephemeral panel state — which tab is open, which swatch is selected.
|
|
36
|
+
*
|
|
37
|
+
* Deliberately outside the document: none of it should be serialized, undoable,
|
|
38
|
+
* or survive the editor closing.
|
|
39
|
+
*/
|
|
40
|
+
export function UiStateProvider({ children }: { children?: React.ReactNode }) {
|
|
41
|
+
const ref = useRef<UiStateStore | null>(null)
|
|
42
|
+
if (!ref.current) ref.current = createUiStateStore()
|
|
43
|
+
return <UiStateContext.Provider value={ref.current}>{children}</UiStateContext.Provider>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Read and write one key of the ephemeral UI state. Throws outside an `<Editor>`. */
|
|
47
|
+
export function useUiState<T>(key: string, fallback: T): [T, (value: T) => void] {
|
|
48
|
+
const store = useContext(UiStateContext)
|
|
49
|
+
if (!store) throw new Error('useUiState must be used inside <Editor> (UiStateProvider)')
|
|
50
|
+
const value = useSyncExternalStore(
|
|
51
|
+
store.subscribe,
|
|
52
|
+
() => store.get(key, fallback),
|
|
53
|
+
() => store.get(key, fallback),
|
|
54
|
+
)
|
|
55
|
+
const set = useCallback((v: T) => store.set(key, v), [store, key])
|
|
56
|
+
return [value, set]
|
|
57
|
+
}
|