@omerdlw/base-framework 1.0.6 → 2.0.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/dist/atoms/index.js +1 -103
- package/dist/atoms/index.js.map +1 -1
- package/dist/chunk-3BUP64Q6.js +105 -0
- package/dist/chunk-3BUP64Q6.js.map +1 -0
- package/dist/chunk-3MSK4XGK.js +9888 -0
- package/dist/chunk-3MSK4XGK.js.map +1 -0
- package/dist/chunk-4GMQKD6F.js +353 -0
- package/dist/chunk-4GMQKD6F.js.map +1 -0
- package/dist/chunk-65ZB4QTQ.js +888 -0
- package/dist/chunk-65ZB4QTQ.js.map +1 -0
- package/dist/chunk-6SG7V77J.js +577 -0
- package/dist/chunk-6SG7V77J.js.map +1 -0
- package/dist/chunk-7HQMXTNP.js +419 -0
- package/dist/chunk-7HQMXTNP.js.map +1 -0
- package/dist/chunk-7TAVYJ3A.js +371 -0
- package/dist/chunk-7TAVYJ3A.js.map +1 -0
- package/dist/chunk-AQ4BNXA2.js +349 -0
- package/dist/chunk-AQ4BNXA2.js.map +1 -0
- package/dist/chunk-CGHZSSFR.js +2166 -0
- package/dist/chunk-CGHZSSFR.js.map +1 -0
- package/dist/chunk-DGCQWQLZ.js +61 -0
- package/dist/chunk-DGCQWQLZ.js.map +1 -0
- package/dist/chunk-FIMPHODX.js +67 -0
- package/dist/chunk-FIMPHODX.js.map +1 -0
- package/dist/chunk-GF7TUX5I.js +1889 -0
- package/dist/chunk-GF7TUX5I.js.map +1 -0
- package/dist/chunk-JELG4JLT.js +454 -0
- package/dist/chunk-JELG4JLT.js.map +1 -0
- package/dist/chunk-K676GL7Z.js +51 -0
- package/dist/chunk-K676GL7Z.js.map +1 -0
- package/dist/chunk-KKQT46TP.js +26 -0
- package/dist/chunk-KKQT46TP.js.map +1 -0
- package/dist/chunk-QI3ALLIB.js +38 -0
- package/dist/chunk-QI3ALLIB.js.map +1 -0
- package/dist/chunk-QXR55VVS.js +1139 -0
- package/dist/chunk-QXR55VVS.js.map +1 -0
- package/dist/chunk-R2YGFJDJ.js +408 -0
- package/dist/chunk-R2YGFJDJ.js.map +1 -0
- package/dist/chunk-RFZQWLC5.js +27 -0
- package/dist/chunk-RFZQWLC5.js.map +1 -0
- package/dist/chunk-SYAVGTOX.js +521 -0
- package/dist/chunk-SYAVGTOX.js.map +1 -0
- package/dist/chunk-TV3WEF5G.js +784 -0
- package/dist/chunk-TV3WEF5G.js.map +1 -0
- package/dist/chunk-XASQT4CQ.js +280 -0
- package/dist/chunk-XASQT4CQ.js.map +1 -0
- package/dist/error/index.js +5 -682
- package/dist/error/index.js.map +1 -1
- package/dist/error/reporter.d.ts.map +1 -1
- package/dist/error/theme.d.ts +1 -1
- package/dist/error/theme.d.ts.map +1 -1
- package/dist/events.js +1 -7
- package/dist/events.js.map +1 -1
- package/dist/hooks/index.js +1 -358
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-global-event.d.ts +1 -1
- package/dist/index.js +18 -20029
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.js +2 -2035
- package/dist/kernel/index.js.map +1 -1
- package/dist/kernel/types.d.ts +1 -1
- package/dist/modules/ambient/analyze.d.ts +46 -0
- package/dist/modules/ambient/analyze.d.ts.map +1 -0
- package/dist/modules/ambient/constants.d.ts +1 -5
- package/dist/modules/ambient/constants.d.ts.map +1 -1
- package/dist/modules/ambient/context.d.ts.map +1 -1
- package/dist/modules/ambient/dom.d.ts +11 -12
- package/dist/modules/ambient/dom.d.ts.map +1 -1
- package/dist/modules/ambient/extractor.d.ts +10 -10
- package/dist/modules/ambient/extractor.d.ts.map +1 -1
- package/dist/modules/ambient/hooks.d.ts +1 -1
- package/dist/modules/ambient/hooks.d.ts.map +1 -1
- package/dist/modules/ambient/index.d.ts +6 -4
- package/dist/modules/ambient/index.d.ts.map +1 -1
- package/dist/modules/ambient/index.js +7 -762
- package/dist/modules/ambient/index.js.map +1 -1
- package/dist/modules/ambient/module.d.ts +1 -1
- package/dist/modules/ambient/module.d.ts.map +1 -1
- package/dist/modules/ambient/oklab.d.ts +36 -0
- package/dist/modules/ambient/oklab.d.ts.map +1 -0
- package/dist/modules/ambient/pipeline.d.ts +28 -0
- package/dist/modules/ambient/pipeline.d.ts.map +1 -0
- package/dist/modules/ambient/quantize.d.ts +22 -0
- package/dist/modules/ambient/quantize.d.ts.map +1 -0
- package/dist/modules/ambient/server/address.d.ts +8 -0
- package/dist/modules/ambient/server/address.d.ts.map +1 -0
- package/dist/modules/ambient/server/index.d.ts +53 -0
- package/dist/modules/ambient/server/index.d.ts.map +1 -0
- package/dist/modules/ambient/server/index.js +221 -0
- package/dist/modules/ambient/server/index.js.map +1 -0
- package/dist/modules/ambient/settings.d.ts +19 -0
- package/dist/modules/ambient/settings.d.ts.map +1 -0
- package/dist/modules/ambient/types.d.ts +105 -9
- package/dist/modules/ambient/types.d.ts.map +1 -1
- package/dist/modules/ambient/worker/index.d.ts +15 -0
- package/dist/modules/ambient/worker/index.d.ts.map +1 -0
- package/dist/modules/ambient/worker/index.js +114 -0
- package/dist/modules/ambient/worker/index.js.map +1 -0
- package/dist/modules/background/constants.d.ts +2 -2
- package/dist/modules/background/constants.d.ts.map +1 -1
- package/dist/modules/background/hooks.d.ts +1 -1
- package/dist/modules/background/index.js +6 -3078
- package/dist/modules/background/index.js.map +1 -1
- package/dist/modules/background/motion.d.ts +9 -7
- package/dist/modules/background/motion.d.ts.map +1 -1
- package/dist/modules/background/overlay.d.ts +3 -8
- package/dist/modules/background/overlay.d.ts.map +1 -1
- package/dist/modules/background/types.d.ts +16 -2
- package/dist/modules/background/types.d.ts.map +1 -1
- package/dist/modules/context-menu/constants.d.ts +2 -2
- package/dist/modules/context-menu/constants.d.ts.map +1 -1
- package/dist/modules/context-menu/hooks.d.ts +1 -1
- package/dist/modules/context-menu/index.js +10 -1896
- package/dist/modules/context-menu/index.js.map +1 -1
- package/dist/modules/context-menu/motion.d.ts +1 -8
- package/dist/modules/context-menu/motion.d.ts.map +1 -1
- package/dist/modules/context-menu/overlay.d.ts.map +1 -1
- package/dist/modules/context-menu/types.d.ts +16 -2
- package/dist/modules/context-menu/types.d.ts.map +1 -1
- package/dist/modules/controls/constants.d.ts +1 -1
- package/dist/modules/controls/constants.d.ts.map +1 -1
- package/dist/modules/controls/entries.d.ts +1 -1
- package/dist/modules/controls/hooks.d.ts +1 -1
- package/dist/modules/controls/index.js +4 -1110
- package/dist/modules/controls/index.js.map +1 -1
- package/dist/modules/controls/overlay.d.ts +1 -1
- package/dist/modules/controls/types.d.ts +2 -2
- package/dist/modules/dock/cards.d.ts +708 -24
- package/dist/modules/dock/cards.d.ts.map +1 -1
- package/dist/modules/dock/constants.d.ts +2 -2
- package/dist/modules/dock/constants.d.ts.map +1 -1
- package/dist/modules/dock/helpers.d.ts +2 -2
- package/dist/modules/dock/hooks.d.ts +2 -2
- package/dist/modules/dock/index.d.ts +1 -1
- package/dist/modules/dock/index.d.ts.map +1 -1
- package/dist/modules/dock/index.js +9 -12132
- package/dist/modules/dock/index.js.map +1 -1
- package/dist/modules/dock/module.d.ts +1 -1
- package/dist/modules/dock/motion.d.ts +41 -915
- package/dist/modules/dock/motion.d.ts.map +1 -1
- package/dist/modules/dock/overlay.d.ts.map +1 -1
- package/dist/modules/dock/runtime/dock.d.ts +1 -23
- package/dist/modules/dock/runtime/dock.d.ts.map +1 -1
- package/dist/modules/dock/styles.d.ts +4 -4
- package/dist/modules/dock/surface/hooks.d.ts +5 -20
- package/dist/modules/dock/surface/hooks.d.ts.map +1 -1
- package/dist/modules/dock/surface/machine.d.ts +4 -3
- package/dist/modules/dock/surface/machine.d.ts.map +1 -1
- package/dist/modules/dock/surface/stack.d.ts.map +1 -1
- package/dist/modules/dock/types.d.ts +158 -3
- package/dist/modules/dock/types.d.ts.map +1 -1
- package/dist/modules/index.js +16 -17883
- package/dist/modules/index.js.map +1 -1
- package/dist/modules/loading/constants.d.ts +1 -1
- package/dist/modules/loading/constants.d.ts.map +1 -1
- package/dist/modules/loading/context.d.ts +1 -1
- package/dist/modules/loading/hooks.d.ts +1 -1
- package/dist/modules/loading/index.js +5 -1153
- package/dist/modules/loading/index.js.map +1 -1
- package/dist/modules/loading/types.d.ts +2 -2
- package/dist/modules/media/context.d.ts +1 -1
- package/dist/modules/media/index.js +3 -570
- package/dist/modules/media/index.js.map +1 -1
- package/dist/modules/media/types.d.ts +2 -2
- package/dist/modules/modal/constants.d.ts +2 -2
- package/dist/modules/modal/constants.d.ts.map +1 -1
- package/dist/modules/modal/context.d.ts +1 -1
- package/dist/modules/modal/hooks.d.ts +3 -3
- package/dist/modules/modal/index.js +8 -2355
- package/dist/modules/modal/index.js.map +1 -1
- package/dist/modules/modal/motion.d.ts +3 -8
- package/dist/modules/modal/motion.d.ts.map +1 -1
- package/dist/modules/modal/overlay.d.ts.map +1 -1
- package/dist/modules/modal/types.d.ts +21 -0
- package/dist/modules/modal/types.d.ts.map +1 -1
- package/dist/modules/notification/constants.d.ts +2 -2
- package/dist/modules/notification/constants.d.ts.map +1 -1
- package/dist/modules/notification/context.d.ts +1 -1
- package/dist/modules/notification/hooks.d.ts +1 -1
- package/dist/modules/notification/index.js +4 -828
- package/dist/modules/notification/index.js.map +1 -1
- package/dist/modules/notification/motion.d.ts +1 -7
- package/dist/modules/notification/motion.d.ts.map +1 -1
- package/dist/modules/notification/overlay.d.ts.map +1 -1
- package/dist/modules/notification/types.d.ts +9 -1
- package/dist/modules/notification/types.d.ts.map +1 -1
- package/dist/overlay-TZ6L52A5.js +9 -0
- package/dist/overlay-TZ6L52A5.js.map +1 -0
- package/dist/provider.d.ts +1 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +6 -1968
- package/dist/provider.js.map +1 -1
- package/dist/result.js +2 -63
- package/dist/result.js.map +1 -1
- package/dist/theme.d.ts +45 -8
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +3 -41
- package/dist/theme.js.map +1 -1
- package/dist/tokens/index.d.ts +1 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +126 -155
- package/dist/tokens/index.js.map +1 -1
- package/dist/tokens/motion-config.d.ts +44 -0
- package/dist/tokens/motion-config.d.ts.map +1 -0
- package/dist/tokens/motion.d.ts +23 -174
- package/dist/tokens/motion.d.ts.map +1 -1
- package/dist/utils/index.js +4 -82
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/report.d.ts.map +1 -1
- package/docs/README.md +1 -0
- package/docs/architecture-and-rules.md +4 -3
- package/docs/core-engine.md +7 -10
- package/docs/getting-started.md +4 -2
- package/docs/modules/ambient.md +194 -80
- package/docs/modules/background.md +3 -3
- package/docs/modules/context-menu.md +2 -2
- package/docs/modules/dock.md +8 -5
- package/docs/modules/modal.md +2 -2
- package/docs/modules/notification.md +2 -2
- package/docs/theming.md +81 -9
- package/package.json +22 -5
- package/templates/AGENTS.md +1 -1
- package/templates/motion/background.ts +17 -0
- package/templates/motion/context-menu.ts +63 -0
- package/templates/motion/dock.ts +327 -0
- package/templates/motion/modal.ts +79 -0
- package/templates/motion/notification.ts +27 -0
- package/templates/motion/tokens.ts +47 -0
- package/templates/tsconfig.json +7 -0
- package/dist/modules/ambient/color.d.ts +0 -21
- package/dist/modules/ambient/color.d.ts.map +0 -1
|
@@ -1,573 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
function getOrCreateGlobalContext(name, defaultValue) {
|
|
6
|
-
const sym = /* @__PURE__ */ Symbol.for(`@omerdlw/base-framework/context/${name}`);
|
|
7
|
-
const store = globalThis;
|
|
8
|
-
if (!store[sym]) {
|
|
9
|
-
store[sym] = createContext(defaultValue);
|
|
10
|
-
}
|
|
11
|
-
return store[sym];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// src/utils/object.ts
|
|
15
|
-
function shallowEqual(a, b) {
|
|
16
|
-
if (Object.is(a, b)) return true;
|
|
17
|
-
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
const keysA = Object.keys(a);
|
|
21
|
-
const keysB = Object.keys(b);
|
|
22
|
-
if (keysA.length !== keysB.length) return false;
|
|
23
|
-
for (const key of keysA) {
|
|
24
|
-
if (!Object.prototype.hasOwnProperty.call(b, key) || !Object.is(
|
|
25
|
-
a[key],
|
|
26
|
-
b[key]
|
|
27
|
-
)) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
function report(scope, error, level = "error") {
|
|
34
|
-
if (process.env.NODE_ENV === "production" && typeof window !== "undefined") {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
console[level](`[${scope}]`, error);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// src/utils/store.ts
|
|
41
|
-
function freezeStoreSnapshot(state) {
|
|
42
|
-
if (process.env.NODE_ENV === "production" || !state || typeof state !== "object") {
|
|
43
|
-
return state;
|
|
44
|
-
}
|
|
45
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
46
|
-
const freeze = (value) => {
|
|
47
|
-
if (seen.has(value) || Object.isFrozen(value)) return;
|
|
48
|
-
seen.add(value);
|
|
49
|
-
const prototype = Object.getPrototypeOf(value);
|
|
50
|
-
if (Array.isArray(value) || prototype === Object.prototype || prototype === null) {
|
|
51
|
-
for (const key of Reflect.ownKeys(value)) {
|
|
52
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
53
|
-
if (descriptor && "value" in descriptor && descriptor.value !== null) {
|
|
54
|
-
if (typeof descriptor.value === "object") freeze(descriptor.value);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
Object.freeze(value);
|
|
59
|
-
};
|
|
60
|
-
freeze(state);
|
|
61
|
-
return state;
|
|
62
|
-
}
|
|
63
|
-
function createStore(initialState, { freezeSnapshots = true } = {}) {
|
|
64
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
65
|
-
const prepare = freezeSnapshots ? freezeStoreSnapshot : (state) => state;
|
|
66
|
-
let snapshot = prepare(initialState);
|
|
67
|
-
const publish = (nextStateOrUpdater) => {
|
|
68
|
-
const nextState = typeof nextStateOrUpdater === "function" ? nextStateOrUpdater(snapshot) : nextStateOrUpdater;
|
|
69
|
-
if (Object.is(snapshot, nextState)) return false;
|
|
70
|
-
snapshot = prepare(nextState);
|
|
71
|
-
for (const listener of listeners) {
|
|
72
|
-
try {
|
|
73
|
-
listener();
|
|
74
|
-
} catch (error) {
|
|
75
|
-
report("CoreStore subscriber", error, "warn");
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return true;
|
|
79
|
-
};
|
|
80
|
-
const setState = (updater) => {
|
|
81
|
-
if (typeof updater === "function") {
|
|
82
|
-
return publish(updater);
|
|
83
|
-
}
|
|
84
|
-
if (snapshot && typeof snapshot === "object" && updater && typeof updater === "object") {
|
|
85
|
-
return publish({ ...snapshot, ...updater });
|
|
86
|
-
}
|
|
87
|
-
return publish(updater);
|
|
88
|
-
};
|
|
89
|
-
return Object.freeze({
|
|
90
|
-
getSnapshot() {
|
|
91
|
-
return snapshot;
|
|
92
|
-
},
|
|
93
|
-
publish,
|
|
94
|
-
setState,
|
|
95
|
-
subscribe(listener) {
|
|
96
|
-
if (typeof listener !== "function") return () => {
|
|
97
|
-
};
|
|
98
|
-
listeners.add(listener);
|
|
99
|
-
return () => listeners.delete(listener);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
function useRequiredContext(context, hookName, providerName) {
|
|
104
|
-
const value = use(context);
|
|
105
|
-
if (value === null) {
|
|
106
|
-
throw new Error(`${hookName} must be used within ${providerName}`);
|
|
107
|
-
}
|
|
108
|
-
return value;
|
|
109
|
-
}
|
|
110
|
-
function useStore(store, selector = (state) => state, isEqual = Object.is) {
|
|
111
|
-
const cacheRef = useRef({
|
|
112
|
-
isEqual: null,
|
|
113
|
-
selected: void 0,
|
|
114
|
-
selector: null,
|
|
115
|
-
snapshot: null
|
|
116
|
-
});
|
|
117
|
-
const getSelectedSnapshot = useCallback(() => {
|
|
118
|
-
const snapshot = store.getSnapshot();
|
|
119
|
-
const cache = cacheRef.current;
|
|
120
|
-
if (cache.snapshot === snapshot && cache.selector === selector && cache.isEqual === isEqual) {
|
|
121
|
-
return cache.selected;
|
|
122
|
-
}
|
|
123
|
-
const selected = selector(snapshot);
|
|
124
|
-
if (cache.snapshot !== null && cache.isEqual === isEqual && isEqual(cache.selected, selected)) {
|
|
125
|
-
cache.snapshot = snapshot;
|
|
126
|
-
cache.selector = selector;
|
|
127
|
-
return cache.selected;
|
|
128
|
-
}
|
|
129
|
-
cacheRef.current = {
|
|
130
|
-
isEqual,
|
|
131
|
-
selected,
|
|
132
|
-
selector,
|
|
133
|
-
snapshot
|
|
134
|
-
};
|
|
135
|
-
return selected;
|
|
136
|
-
}, [isEqual, selector, store]);
|
|
137
|
-
return useSyncExternalStore(
|
|
138
|
-
store.subscribe,
|
|
139
|
-
getSelectedSnapshot,
|
|
140
|
-
getSelectedSnapshot
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
var RegistryContext = getOrCreateGlobalContext(
|
|
144
|
-
"RegistryContext",
|
|
145
|
-
null
|
|
146
|
-
);
|
|
147
|
-
function useRegistrySubscription() {
|
|
148
|
-
return useRequiredContext(
|
|
149
|
-
RegistryContext,
|
|
150
|
-
"useRegistrySubscription",
|
|
151
|
-
"RegistryProvider"
|
|
152
|
-
).subscription;
|
|
153
|
-
}
|
|
154
|
-
function useRegistryValue(type, key) {
|
|
155
|
-
const { getSnapshot, subscribe } = useRegistrySubscription();
|
|
156
|
-
const subscribeToKey = useCallback(
|
|
157
|
-
(listener) => subscribe(type, key, listener),
|
|
158
|
-
[key, subscribe, type]
|
|
159
|
-
);
|
|
160
|
-
const getValue = useCallback(
|
|
161
|
-
() => getSnapshot(type, key),
|
|
162
|
-
[getSnapshot, key, type]
|
|
163
|
-
);
|
|
164
|
-
return useSyncExternalStore(subscribeToKey, getValue, getValue);
|
|
165
|
-
}
|
|
166
|
-
function defineModule(coreModule) {
|
|
167
|
-
return Object.freeze({ ...coreModule });
|
|
168
|
-
}
|
|
169
|
-
createStore(void 0);
|
|
170
|
-
|
|
171
|
-
// src/modules/media/constants.ts
|
|
172
|
-
var DEFAULT_MEDIA_STATE = Object.freeze({
|
|
173
|
-
audibleElement: null,
|
|
174
|
-
element: null,
|
|
175
|
-
hasMedia: false,
|
|
176
|
-
isPlaying: false,
|
|
177
|
-
kind: null,
|
|
178
|
-
loop: false,
|
|
179
|
-
sourceId: null
|
|
180
|
-
});
|
|
181
|
-
var INERT_MEDIA_ACTIONS = Object.freeze({
|
|
182
|
-
removeSource: () => {
|
|
183
|
-
},
|
|
184
|
-
setMuted: () => {
|
|
185
|
-
},
|
|
186
|
-
toggle: () => {
|
|
187
|
-
},
|
|
188
|
-
toggleLoop: () => {
|
|
189
|
-
},
|
|
190
|
-
upsertSource: () => {
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
var MEDIA_SYNC_DRIFT_SECONDS = 0.3;
|
|
194
|
-
var MEDIA_REGISTRY_KEY = "page-media";
|
|
195
|
-
var PAGE_MEDIA_ID = "page";
|
|
196
|
-
|
|
197
|
-
// src/modules/media/playback.ts
|
|
198
|
-
var noop = () => {
|
|
199
|
-
};
|
|
200
|
-
function toggleElement(element) {
|
|
201
|
-
if (!element) return;
|
|
202
|
-
if (element.paused || element.ended) {
|
|
203
|
-
void Promise.resolve(element.play()).catch(noop);
|
|
204
|
-
} else {
|
|
205
|
-
element.pause();
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
function safePlay(element) {
|
|
209
|
-
try {
|
|
210
|
-
void Promise.resolve(element.play()).catch(noop);
|
|
211
|
-
} catch {
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
function sameElements(a, b) {
|
|
215
|
-
return a.length === b.length && a.every((element, index) => element === b[index]);
|
|
216
|
-
}
|
|
217
|
-
function bindFollowers(transport, followers) {
|
|
218
|
-
const ownLoops = followers.map((follower) => follower.loop);
|
|
219
|
-
const align = (hard) => {
|
|
220
|
-
const time = Number(transport.currentTime) || 0;
|
|
221
|
-
for (const follower of followers) {
|
|
222
|
-
follower.loop = false;
|
|
223
|
-
if (follower.playbackRate !== transport.playbackRate) {
|
|
224
|
-
follower.playbackRate = transport.playbackRate;
|
|
225
|
-
}
|
|
226
|
-
const drift = Math.abs((Number(follower.currentTime) || 0) - time);
|
|
227
|
-
if (hard || drift > MEDIA_SYNC_DRIFT_SECONDS) follower.currentTime = time;
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
const play = () => {
|
|
231
|
-
align(false);
|
|
232
|
-
followers.forEach(safePlay);
|
|
233
|
-
};
|
|
234
|
-
const pause = () => followers.forEach((follower) => follower.pause());
|
|
235
|
-
const hardAlign = () => align(true);
|
|
236
|
-
const softAlign = () => align(false);
|
|
237
|
-
const listeners = [
|
|
238
|
-
["play", play],
|
|
239
|
-
["playing", play],
|
|
240
|
-
["pause", pause],
|
|
241
|
-
["waiting", pause],
|
|
242
|
-
["ended", pause],
|
|
243
|
-
["seeking", hardAlign],
|
|
244
|
-
["seeked", hardAlign],
|
|
245
|
-
["ratechange", softAlign],
|
|
246
|
-
["timeupdate", softAlign]
|
|
247
|
-
];
|
|
248
|
-
for (const [type, listener] of listeners) {
|
|
249
|
-
transport.addEventListener(type, listener);
|
|
250
|
-
}
|
|
251
|
-
hardAlign();
|
|
252
|
-
if (!transport.paused && !transport.ended) play();
|
|
253
|
-
return () => {
|
|
254
|
-
for (const [type, listener] of listeners) {
|
|
255
|
-
transport.removeEventListener(type, listener);
|
|
256
|
-
}
|
|
257
|
-
followers.forEach((follower, index) => {
|
|
258
|
-
follower.loop = ownLoops[index];
|
|
259
|
-
});
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// src/modules/media/session.ts
|
|
264
|
-
function newest(sources) {
|
|
265
|
-
return sources.reduce((a, b) => b.order > a.order ? b : a);
|
|
266
|
-
}
|
|
267
|
-
function resolveMediaSession(sources) {
|
|
268
|
-
if (sources.length === 0) return null;
|
|
269
|
-
const ids = new Set(sources.map((source) => source.id));
|
|
270
|
-
const wantsFollow = (source) => Boolean(source.follow) && source.follow !== source.id && ids.has(source.follow);
|
|
271
|
-
const rootIds = new Set(
|
|
272
|
-
sources.filter((source) => !wantsFollow(source)).map((source) => source.id)
|
|
273
|
-
);
|
|
274
|
-
const isFollower = (source) => wantsFollow(source) && rootIds.has(source.follow);
|
|
275
|
-
const transport = newest(sources.filter((source) => !isFollower(source)));
|
|
276
|
-
const followers = sources.filter((source) => isFollower(source) && source.follow === transport.id).sort((a, b) => a.order - b.order);
|
|
277
|
-
const audioFollowers = followers.filter((source) => source.kind === "audio");
|
|
278
|
-
return {
|
|
279
|
-
audible: audioFollowers.length > 0 ? newest(audioFollowers) : transport,
|
|
280
|
-
followers,
|
|
281
|
-
transport
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
function createMediaState(session) {
|
|
285
|
-
if (!session) return DEFAULT_MEDIA_STATE;
|
|
286
|
-
const { audible, transport } = session;
|
|
287
|
-
return {
|
|
288
|
-
audibleElement: audible.element,
|
|
289
|
-
element: transport.element,
|
|
290
|
-
hasMedia: true,
|
|
291
|
-
isPlaying: transport.isPlaying,
|
|
292
|
-
kind: transport.kind,
|
|
293
|
-
loop: transport.loop,
|
|
294
|
-
sourceId: transport.id
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
function mediaStatesEqual(a, b) {
|
|
298
|
-
return shallowEqual(a, b);
|
|
299
|
-
}
|
|
300
|
-
function mergeMediaSource(current, input, order) {
|
|
301
|
-
return {
|
|
302
|
-
controls: void 0,
|
|
303
|
-
element: null,
|
|
304
|
-
follow: null,
|
|
305
|
-
isPlaying: false,
|
|
306
|
-
kind: "audio",
|
|
307
|
-
loop: false,
|
|
308
|
-
...current,
|
|
309
|
-
...input,
|
|
310
|
-
order: current?.order ?? order
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
function selectPageMedia(media) {
|
|
314
|
-
if (!media) return null;
|
|
315
|
-
if (typeof media === "string") return { src: media };
|
|
316
|
-
return media.src ? media : null;
|
|
317
|
-
}
|
|
318
|
-
function findDisplacedAudio(entries, session, newId) {
|
|
319
|
-
if (!session || session.transport.id !== newId) return [];
|
|
320
|
-
const followerIds = new Set(session.followers.map((entry) => entry.id));
|
|
321
|
-
return entries.filter(
|
|
322
|
-
(entry) => entry.id !== newId && !followerIds.has(entry.id) && entry.kind === "audio" && entry.element !== null && !entry.element.paused
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
|
-
var MediaContext = getOrCreateGlobalContext(
|
|
326
|
-
"MediaContext",
|
|
327
|
-
null
|
|
328
|
-
);
|
|
329
|
-
var NOOP_MEDIA_STORE = createStore(DEFAULT_MEDIA_STATE);
|
|
330
|
-
function MediaProvider({ children }) {
|
|
331
|
-
const [store] = useState(
|
|
332
|
-
() => createStore(DEFAULT_MEDIA_STATE, { freezeSnapshots: false })
|
|
333
|
-
);
|
|
334
|
-
const sourcesRef = useRef(/* @__PURE__ */ new Map());
|
|
335
|
-
const sessionRef = useRef(null);
|
|
336
|
-
const orderRef = useRef(0);
|
|
337
|
-
const bindingRef = useRef(null);
|
|
338
|
-
const actions = useMemo(() => {
|
|
339
|
-
const unbind = () => {
|
|
340
|
-
bindingRef.current?.cleanup();
|
|
341
|
-
bindingRef.current = null;
|
|
342
|
-
};
|
|
343
|
-
const rebind = (session) => {
|
|
344
|
-
const transport = session?.transport.element ?? null;
|
|
345
|
-
const followers = (session?.followers ?? []).map(
|
|
346
|
-
(source) => source.element
|
|
347
|
-
);
|
|
348
|
-
const current = bindingRef.current;
|
|
349
|
-
if (current && current.transport === transport && sameElements(current.followers, followers)) {
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
unbind();
|
|
353
|
-
const live = followers.filter(
|
|
354
|
-
(element) => element !== null
|
|
355
|
-
);
|
|
356
|
-
if (!transport || live.length === 0) return;
|
|
357
|
-
bindingRef.current = {
|
|
358
|
-
cleanup: bindFollowers(transport, live),
|
|
359
|
-
followers,
|
|
360
|
-
transport
|
|
361
|
-
};
|
|
362
|
-
};
|
|
363
|
-
const commit = () => {
|
|
364
|
-
const session = resolveMediaSession([...sourcesRef.current.values()]);
|
|
365
|
-
sessionRef.current = session;
|
|
366
|
-
rebind(session);
|
|
367
|
-
const next = createMediaState(session);
|
|
368
|
-
store.publish((prev) => mediaStatesEqual(prev, next) ? prev : next);
|
|
369
|
-
};
|
|
370
|
-
const patch = (id, changes) => {
|
|
371
|
-
const current = sourcesRef.current.get(id);
|
|
372
|
-
if (!current) return;
|
|
373
|
-
sourcesRef.current.set(id, { ...current, ...changes });
|
|
374
|
-
commit();
|
|
375
|
-
};
|
|
376
|
-
return {
|
|
377
|
-
removeSource: (id) => {
|
|
378
|
-
if (sourcesRef.current.delete(id)) commit();
|
|
379
|
-
},
|
|
380
|
-
setMuted: (muted) => {
|
|
381
|
-
const audible = sessionRef.current?.audible;
|
|
382
|
-
if (!audible) return;
|
|
383
|
-
if (audible.controls?.setMuted) audible.controls.setMuted(muted);
|
|
384
|
-
else if (audible.element) audible.element.muted = muted;
|
|
385
|
-
},
|
|
386
|
-
toggle: () => {
|
|
387
|
-
const transport = sessionRef.current?.transport;
|
|
388
|
-
if (!transport) return;
|
|
389
|
-
if (transport.controls?.toggle) transport.controls.toggle();
|
|
390
|
-
else toggleElement(transport.element);
|
|
391
|
-
},
|
|
392
|
-
toggleLoop: () => {
|
|
393
|
-
const transport = sessionRef.current?.transport;
|
|
394
|
-
if (!transport) return;
|
|
395
|
-
if (transport.controls?.toggleLoop) {
|
|
396
|
-
transport.controls.toggleLoop();
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
const loop = !transport.loop;
|
|
400
|
-
if (transport.element) transport.element.loop = loop;
|
|
401
|
-
patch(transport.id, { loop });
|
|
402
|
-
},
|
|
403
|
-
upsertSource: (input) => {
|
|
404
|
-
const current = sourcesRef.current.get(input.id);
|
|
405
|
-
if (!current) orderRef.current += 1;
|
|
406
|
-
sourcesRef.current.set(
|
|
407
|
-
input.id,
|
|
408
|
-
mergeMediaSource(current, input, orderRef.current)
|
|
409
|
-
);
|
|
410
|
-
commit();
|
|
411
|
-
if (!current) {
|
|
412
|
-
findDisplacedAudio(
|
|
413
|
-
[...sourcesRef.current.values()],
|
|
414
|
-
sessionRef.current,
|
|
415
|
-
input.id
|
|
416
|
-
).forEach((entry) => entry.element?.pause());
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
};
|
|
420
|
-
}, [store]);
|
|
421
|
-
useEffect(
|
|
422
|
-
() => () => {
|
|
423
|
-
bindingRef.current?.cleanup();
|
|
424
|
-
bindingRef.current = null;
|
|
425
|
-
},
|
|
426
|
-
[]
|
|
427
|
-
);
|
|
428
|
-
const value = useMemo(
|
|
429
|
-
() => ({ actions, store }),
|
|
430
|
-
[actions, store]
|
|
431
|
-
);
|
|
432
|
-
return /* @__PURE__ */ jsx(MediaContext, { value, children });
|
|
433
|
-
}
|
|
434
|
-
function useMediaState() {
|
|
435
|
-
const { store } = useRequiredContext(
|
|
436
|
-
MediaContext,
|
|
437
|
-
"useMediaState",
|
|
438
|
-
"MediaProvider"
|
|
439
|
-
);
|
|
440
|
-
return useStore(store);
|
|
441
|
-
}
|
|
442
|
-
function useMediaActions() {
|
|
443
|
-
return useRequiredContext(MediaContext, "useMediaActions", "MediaProvider").actions;
|
|
444
|
-
}
|
|
445
|
-
function useOptionalMediaState(selector, isEqual) {
|
|
446
|
-
const ctx = useContext(MediaContext);
|
|
447
|
-
return useStore(
|
|
448
|
-
ctx?.store ?? NOOP_MEDIA_STORE,
|
|
449
|
-
selector,
|
|
450
|
-
isEqual
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
function useOptionalMediaActions() {
|
|
454
|
-
const ctx = useContext(MediaContext);
|
|
455
|
-
return ctx?.actions ?? INERT_MEDIA_ACTIONS;
|
|
456
|
-
}
|
|
457
|
-
function useMedia(options) {
|
|
458
|
-
const generatedId = useId();
|
|
459
|
-
const id = options.id ?? `media-${generatedId}`;
|
|
460
|
-
const { removeSource, upsertSource } = useMediaActions();
|
|
461
|
-
const audioRef = useRef(null);
|
|
462
|
-
const optionsRef = useRef(options);
|
|
463
|
-
const { src, enabled = true } = options;
|
|
464
|
-
const isEnabled = enabled && Boolean(src);
|
|
465
|
-
useEffect(() => {
|
|
466
|
-
optionsRef.current = options;
|
|
467
|
-
});
|
|
468
|
-
useEffect(() => {
|
|
469
|
-
if (!isEnabled || !src) return void 0;
|
|
470
|
-
const audio = new Audio();
|
|
471
|
-
audio.preload = "auto";
|
|
472
|
-
audio.src = src;
|
|
473
|
-
audioRef.current = audio;
|
|
474
|
-
const initial = optionsRef.current;
|
|
475
|
-
audio.loop = Boolean(initial.loop);
|
|
476
|
-
audio.muted = Boolean(initial.muted);
|
|
477
|
-
if (typeof initial.volume === "number") {
|
|
478
|
-
audio.volume = Math.min(1, Math.max(0, initial.volume));
|
|
479
|
-
}
|
|
480
|
-
upsertSource({
|
|
481
|
-
element: audio,
|
|
482
|
-
follow: initial.follow ?? null,
|
|
483
|
-
id,
|
|
484
|
-
isPlaying: false,
|
|
485
|
-
kind: "audio",
|
|
486
|
-
loop: audio.loop
|
|
487
|
-
});
|
|
488
|
-
const syncPlaying = () => upsertSource({ id, isPlaying: !audio.paused && !audio.ended });
|
|
489
|
-
const events = ["play", "playing", "pause", "ended"];
|
|
490
|
-
events.forEach((type) => audio.addEventListener(type, syncPlaying));
|
|
491
|
-
if (!initial.follow && initial.autoplay !== false) {
|
|
492
|
-
void Promise.resolve(audio.play()).catch(() => {
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
return () => {
|
|
496
|
-
events.forEach((type) => audio.removeEventListener(type, syncPlaying));
|
|
497
|
-
audio.pause();
|
|
498
|
-
audio.removeAttribute("src");
|
|
499
|
-
audio.load();
|
|
500
|
-
audioRef.current = null;
|
|
501
|
-
removeSource(id);
|
|
502
|
-
};
|
|
503
|
-
}, [id, isEnabled, removeSource, src, upsertSource]);
|
|
504
|
-
const { follow = null, loop, muted, volume } = options;
|
|
505
|
-
useEffect(() => {
|
|
506
|
-
const audio = audioRef.current;
|
|
507
|
-
if (!audio) return;
|
|
508
|
-
if (loop !== void 0 && !follow) audio.loop = loop;
|
|
509
|
-
if (muted !== void 0) audio.muted = muted;
|
|
510
|
-
if (volume !== void 0) audio.volume = Math.min(1, Math.max(0, volume));
|
|
511
|
-
upsertSource({ follow, id, ...follow ? {} : { loop: audio.loop } });
|
|
512
|
-
}, [follow, id, isEnabled, loop, muted, src, upsertSource, volume]);
|
|
513
|
-
const play = useCallback(() => {
|
|
514
|
-
const audio = audioRef.current;
|
|
515
|
-
if (audio) void Promise.resolve(audio.play()).catch(() => {
|
|
516
|
-
});
|
|
517
|
-
}, []);
|
|
518
|
-
const pause = useCallback(() => audioRef.current?.pause(), []);
|
|
519
|
-
const toggle = useCallback(() => toggleElement(audioRef.current), []);
|
|
520
|
-
return useMemo(
|
|
521
|
-
() => ({ id, pause, play, toggle }),
|
|
522
|
-
[id, pause, play, toggle]
|
|
523
|
-
);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
// src/modules/media/overlay.tsx
|
|
527
|
-
function MediaSource(props) {
|
|
528
|
-
useMedia(props);
|
|
529
|
-
return null;
|
|
530
|
-
}
|
|
531
|
-
function MediaOverlay() {
|
|
532
|
-
const page = useRegistryValue(
|
|
533
|
-
"media",
|
|
534
|
-
MEDIA_REGISTRY_KEY
|
|
535
|
-
);
|
|
536
|
-
useMedia({ ...page, id: PAGE_MEDIA_ID, src: page?.src });
|
|
537
|
-
return null;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// src/modules/media/module.tsx
|
|
541
|
-
function useMediaPage(_slice, page) {
|
|
542
|
-
const actions = useMediaActions();
|
|
543
|
-
return useMemo(
|
|
544
|
-
() => ({
|
|
545
|
-
...actions,
|
|
546
|
-
set: (media) => page.set({ media })
|
|
547
|
-
}),
|
|
548
|
-
[actions, page]
|
|
549
|
-
);
|
|
550
|
-
}
|
|
551
|
-
var mediaModule = defineModule({
|
|
552
|
-
id: "media",
|
|
553
|
-
context: MediaContext,
|
|
554
|
-
Provider: MediaProvider,
|
|
555
|
-
Overlay: MediaOverlay,
|
|
556
|
-
registry: {
|
|
557
|
-
cleanupDelayMs: 600,
|
|
558
|
-
keyPolicy: "singleton",
|
|
559
|
-
lifecycle: "immediate",
|
|
560
|
-
singletonKey: MEDIA_REGISTRY_KEY
|
|
561
|
-
},
|
|
562
|
-
page: {
|
|
563
|
-
select: (config) => selectPageMedia(config.media),
|
|
564
|
-
entries: (slice) => [
|
|
565
|
-
{ key: MEDIA_REGISTRY_KEY, value: slice }
|
|
566
|
-
],
|
|
567
|
-
use: useMediaPage
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
|
-
|
|
571
|
-
export { DEFAULT_MEDIA_STATE, INERT_MEDIA_ACTIONS, MEDIA_REGISTRY_KEY, MEDIA_SYNC_DRIFT_SECONDS, MediaContext, MediaOverlay, MediaProvider, MediaSource, NOOP_MEDIA_STORE, PAGE_MEDIA_ID, bindFollowers, createMediaState, findDisplacedAudio, mediaModule, mediaStatesEqual, mergeMediaSource, resolveMediaSession, safePlay, sameElements, selectPageMedia, toggleElement, useMedia, useMediaActions, useMediaState, useOptionalMediaActions, useOptionalMediaState };
|
|
2
|
+
export { DEFAULT_MEDIA_STATE, INERT_MEDIA_ACTIONS, MEDIA_REGISTRY_KEY, MEDIA_SYNC_DRIFT_SECONDS, MediaContext, MediaOverlay, MediaProvider, MediaSource, NOOP_MEDIA_STORE, PAGE_MEDIA_ID, bindFollowers, createMediaState, findDisplacedAudio, mediaModule, mediaStatesEqual, mergeMediaSource, resolveMediaSession, safePlay, sameElements, selectPageMedia, toggleElement, useMedia, useMediaActions, useMediaState, useOptionalMediaActions, useOptionalMediaState } from '../../chunk-R2YGFJDJ.js';
|
|
3
|
+
import '../../chunk-GF7TUX5I.js';
|
|
4
|
+
import '../../chunk-TV3WEF5G.js';
|
|
572
5
|
//# sourceMappingURL=index.js.map
|
|
573
6
|
//# sourceMappingURL=index.js.map
|