@templatical/core 0.34.3 → 0.36.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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { i as useEditor, n as UseEditorOptions, r as UseEditorReturn, t as EditorState } from "./editor-Bl4WsPU3.js";
2
- import { Block, BlockDefaults, BlockType, Comment, CommentAuthor, CommentInput, CommentPatch, CommentsListParams, CommentsProvider, CustomBlock, CustomBlockDefinition, SavedBlock, SavedBlockPatch, SavedBlocksListParams, SavedBlocksProvider, Template, TemplateContent, TemplateSettings, TemplateVersion, VersionHistoryListParams, VersionHistoryProvider } from "@templatical/types";
2
+ import { Block, BlockDefaults, BlockType, Comment, CommentAuthor, CommentInput, CommentPatch, CommentsListParams, CommentsProvider, CustomBlock, CustomBlockDefinition, MediaProvider, SavedBlock, SavedBlockPatch, SavedBlocksListParams, SavedBlocksProvider, Template, TemplateContent, TemplateSettings, TemplateVersion, VersionHistoryListParams, VersionHistoryProvider } from "@templatical/types";
3
3
  import { ComputedRef, Ref } from "@vue/reactivity";
4
4
  import { ComputedRef as ComputedRef$1, Ref as Ref$1 } from "vue";
5
5
  //#region src/history.d.ts
@@ -231,6 +231,31 @@ interface LocalStorageSavedBlocksOptions {
231
231
  */
232
232
  export declare function createLocalStorageSavedBlocksProvider(options?: LocalStorageSavedBlocksOptions): SavedBlocksProvider;
233
233
  //#endregion
234
+ //#region src/media-local.d.ts
235
+ interface LocalStorageMediaProviderOptions {
236
+ /**
237
+ * `localStorage` key holding the serialized array.
238
+ *
239
+ * @default "templatical:media"
240
+ */
241
+ key?: string;
242
+ }
243
+ /**
244
+ * Browser-local {@link MediaProvider} backed by `localStorage`.
245
+ *
246
+ * Opt-in: pass it explicitly as `init({ media: createLocalStorageMediaProvider() })`.
247
+ * The editor never falls back to it, so consumers without a provider keep
248
+ * image fields URL-only.
249
+ *
250
+ * `create` stores the file as a data URL. That is a demo-sized persistence
251
+ * model — `localStorage` quotas are typically ~5 MB, and a few large
252
+ * images will fill it. Back a real gallery with your own API.
253
+ *
254
+ * Folders, replace, import, usage, frequently-used and quota are `false`:
255
+ * this adapter is a flat list of assets.
256
+ */
257
+ export declare function createLocalStorageMediaProvider(options?: LocalStorageMediaProviderOptions): MediaProvider;
258
+ //#endregion
234
259
  //#region src/version-history.d.ts
235
260
  interface UseVersionHistoryOptions {
236
261
  /**
@@ -394,5 +419,5 @@ interface UseCommentListenerOptions {
394
419
  */
395
420
  export declare function useCommentListener(options: UseCommentListenerOptions): void;
396
421
  //#endregion
397
- export { type EditorState, type LocalStorageSavedBlocksOptions, type UseAutoSaveOptions, type UseAutoSaveReturn, type UseBlockActionsOptions, type UseBlockActionsReturn, type UseCommentListenerOptions, type UseCommentsOptions, type UseCommentsReturn, type UseConditionPreviewReturn, type UseEditorOptions, type UseEditorReturn, type UseHistoryOptions, type UseHistoryReturn, type UseSavedBlocksOptions, type UseSavedBlocksReturn, type UseVersionHistoryOptions, type UseVersionHistoryReturn, useEditor };
422
+ export { type EditorState, type LocalStorageMediaProviderOptions, type LocalStorageSavedBlocksOptions, type UseAutoSaveOptions, type UseAutoSaveReturn, type UseBlockActionsOptions, type UseBlockActionsReturn, type UseCommentListenerOptions, type UseCommentsOptions, type UseCommentsReturn, type UseConditionPreviewReturn, type UseEditorOptions, type UseEditorReturn, type UseHistoryOptions, type UseHistoryReturn, type UseSavedBlocksOptions, type UseSavedBlocksReturn, type UseVersionHistoryOptions, type UseVersionHistoryReturn, useEditor };
398
423
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -796,7 +796,7 @@ function useSavedBlocks(options) {
796
796
  }
797
797
  //#endregion
798
798
  //#region src/saved-blocks-local.ts
799
- const DEFAULT_KEY = "templatical:saved-blocks";
799
+ const DEFAULT_KEY$1 = "templatical:saved-blocks";
800
800
  /**
801
801
  * Browser-local {@link SavedBlocksProvider} backed by `localStorage`.
802
802
  *
@@ -810,7 +810,7 @@ const DEFAULT_KEY = "templatical:saved-blocks";
810
810
  * that needs to outlive a browser profile.
811
811
  */
812
812
  function createLocalStorageSavedBlocksProvider(options = {}) {
813
- const storageKey = options.key ?? DEFAULT_KEY;
813
+ const storageKey = options.key ?? DEFAULT_KEY$1;
814
814
  function getStorage() {
815
815
  if (typeof localStorage === "undefined") throw new Error("[Templatical] createLocalStorageSavedBlocksProvider requires a browser environment with localStorage. Supply your own SavedBlocksProvider for server-side or non-browser use.");
816
816
  return localStorage;
@@ -874,6 +874,125 @@ function createLocalStorageSavedBlocksProvider(options = {}) {
874
874
  };
875
875
  }
876
876
  //#endregion
877
+ //#region src/media-local.ts
878
+ const DEFAULT_KEY = "templatical:media";
879
+ const PAGE_SIZE = 50;
880
+ /**
881
+ * Browser-local {@link MediaProvider} backed by `localStorage`.
882
+ *
883
+ * Opt-in: pass it explicitly as `init({ media: createLocalStorageMediaProvider() })`.
884
+ * The editor never falls back to it, so consumers without a provider keep
885
+ * image fields URL-only.
886
+ *
887
+ * `create` stores the file as a data URL. That is a demo-sized persistence
888
+ * model — `localStorage` quotas are typically ~5 MB, and a few large
889
+ * images will fill it. Back a real gallery with your own API.
890
+ *
891
+ * Folders, replace, import, usage, frequently-used and quota are `false`:
892
+ * this adapter is a flat list of assets.
893
+ */
894
+ function createLocalStorageMediaProvider(options = {}) {
895
+ const storageKey = options.key ?? DEFAULT_KEY;
896
+ function getStorage() {
897
+ if (typeof localStorage === "undefined") throw new Error("[Templatical] createLocalStorageMediaProvider requires a browser environment with localStorage. Supply your own MediaProvider for server-side or non-browser use.");
898
+ return localStorage;
899
+ }
900
+ function readAll() {
901
+ const raw = getStorage().getItem(storageKey);
902
+ if (!raw) return [];
903
+ try {
904
+ const parsed = JSON.parse(raw);
905
+ return Array.isArray(parsed) ? parsed : [];
906
+ } catch {
907
+ return [];
908
+ }
909
+ }
910
+ function writeAll(assets) {
911
+ getStorage().setItem(storageKey, JSON.stringify(assets));
912
+ }
913
+ function readFileAsDataURL(file) {
914
+ if (typeof FileReader === "undefined") return Promise.reject(/* @__PURE__ */ new Error("[Templatical] createLocalStorageMediaProvider requires a browser environment with FileReader."));
915
+ return new Promise((resolve, reject) => {
916
+ const reader = new FileReader();
917
+ reader.onload = () => {
918
+ if (typeof reader.result !== "string") {
919
+ reject(/* @__PURE__ */ new Error("[Templatical] Failed to read file as a data URL."));
920
+ return;
921
+ }
922
+ resolve(reader.result);
923
+ };
924
+ reader.onerror = () => {
925
+ reject(reader.error ?? /* @__PURE__ */ new Error("[Templatical] Failed to read file as a data URL."));
926
+ };
927
+ reader.readAsDataURL(file);
928
+ });
929
+ }
930
+ return {
931
+ async list(params) {
932
+ const all = readAll();
933
+ const search = params?.search?.trim().toLowerCase();
934
+ const filtered = search ? all.filter((asset) => {
935
+ const filename = asset.filename?.toLowerCase() ?? "";
936
+ const alt = asset.alt?.toLowerCase() ?? "";
937
+ return filename.includes(search) || alt.includes(search);
938
+ }) : all;
939
+ const parsed = params?.cursor ? Number.parseInt(params.cursor, 10) : 0;
940
+ const offset = Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
941
+ const items = filtered.slice(offset, offset + PAGE_SIZE);
942
+ const page = { items };
943
+ const nextOffset = offset + items.length;
944
+ if (nextOffset < filtered.length) page.nextCursor = String(nextOffset);
945
+ return page;
946
+ },
947
+ async create(input) {
948
+ const url = await readFileAsDataURL(input.file);
949
+ const now = (/* @__PURE__ */ new Date()).toISOString();
950
+ const created = {
951
+ id: generateId(),
952
+ url,
953
+ filename: input.filename || input.file.name,
954
+ createdAt: now,
955
+ updatedAt: now,
956
+ size: input.file.size
957
+ };
958
+ if (input.alt !== void 0) created.alt = input.alt;
959
+ if (input.file.type) created.mimeType = input.file.type;
960
+ if (input.folderId !== void 0) created.folderId = input.folderId;
961
+ writeAll([created, ...readAll()]);
962
+ return created;
963
+ },
964
+ async update(id, patch) {
965
+ const all = readAll();
966
+ const index = all.findIndex((asset) => asset.id === id);
967
+ if (index === -1) throw new Error(`[Templatical] Media asset not found: ${id}`);
968
+ const current = all[index];
969
+ const updated = {
970
+ ...current,
971
+ ...patch,
972
+ id: current.id,
973
+ url: current.url,
974
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
975
+ };
976
+ const next = [...all];
977
+ next[index] = updated;
978
+ writeAll(next);
979
+ return updated;
980
+ },
981
+ async delete(ids) {
982
+ const all = readAll();
983
+ for (const id of ids) if (!all.some((asset) => asset.id === id)) throw new Error(`[Templatical] Media asset not found: ${id}`);
984
+ const remove = new Set(ids);
985
+ writeAll(all.filter((asset) => !remove.has(asset.id)));
986
+ },
987
+ folders: false,
988
+ replace: false,
989
+ importFromUrl: false,
990
+ checkUsage: false,
991
+ frequentlyUsed: false,
992
+ storage: false
993
+ };
994
+ }
995
+ //#endregion
877
996
  //#region src/version-history.ts
878
997
  /**
879
998
  * Reactive state over a {@link VersionHistoryProvider}.
@@ -1299,6 +1418,6 @@ function useCommentListener(options) {
1299
1418
  onScopeDispose(stop);
1300
1419
  }
1301
1420
  //#endregion
1302
- export { DEFAULT_AUTO_SAVE_DEBOUNCE_MS, createLocalStorageSavedBlocksProvider, useAutoSave, useBlockActions, useCommentListener, useComments, useConditionPreview, useDataSourceFetch, useEditor, useHistory, useHistoryInterceptor, useSavedBlocks, useVersionHistory };
1421
+ export { DEFAULT_AUTO_SAVE_DEBOUNCE_MS, createLocalStorageMediaProvider, createLocalStorageSavedBlocksProvider, useAutoSave, useBlockActions, useCommentListener, useComments, useConditionPreview, useDataSourceFetch, useEditor, useHistory, useHistoryInterceptor, useSavedBlocks, useVersionHistory };
1303
1422
 
1304
1423
  //# sourceMappingURL=index.js.map