@inkweave/plugins 1.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.
@@ -0,0 +1,14 @@
1
+ export declare class AudioController {
2
+ private static _sound;
3
+ private static _music;
4
+ private static _sound_handler;
5
+ private static _music_handler;
6
+ static get sound(): HTMLAudioElement | null;
7
+ static get music(): HTMLAudioElement | null;
8
+ static get sound_handler(): () => void;
9
+ static get music_handler(): () => void;
10
+ static set_music(path: string): void;
11
+ static set_sound(path: string): void;
12
+ static cleanupSound(): void;
13
+ static cleanupMusic(): void;
14
+ }
@@ -0,0 +1,2 @@
1
+ declare const load: () => void;
2
+ export default load;
@@ -0,0 +1,3 @@
1
+ import { ChoiceComponentProps } from '@inkweave/react';
2
+ declare const _default: import('react').NamedExoticComponent<ChoiceComponentProps>;
3
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const load: () => void;
2
+ export default load;
@@ -0,0 +1,2 @@
1
+ declare const load: () => void;
2
+ export default load;
@@ -0,0 +1,3 @@
1
+ import { ChoiceComponentProps } from '@inkweave/react';
2
+ declare const _default: import('react').NamedExoticComponent<ChoiceComponentProps>;
3
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const load: () => void;
2
+ export default load;
@@ -0,0 +1,2 @@
1
+ declare const load: () => void;
2
+ export default load;
@@ -0,0 +1,6 @@
1
+ interface ImageProps {
2
+ className?: string;
3
+ fallback?: React.ReactNode;
4
+ }
5
+ declare const _default: import('react').NamedExoticComponent<ImageProps>;
6
+ export default _default;
@@ -0,0 +1,13 @@
1
+ declare module '@inkweave/core' {
2
+ interface InkStory {
3
+ image: string;
4
+ }
5
+ }
6
+ type StoryImage = {
7
+ image: string;
8
+ setImage: (image: string) => void;
9
+ };
10
+ export declare const useStoryImage: import('zustand').UseBoundStore<import('zustand').StoreApi<StoryImage>>;
11
+ declare const load: () => void;
12
+ export default load;
13
+ export { default as Image } from './Image';
package/dist/index.cjs ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";var b=Object.defineProperty;var T=(t,e,s)=>e in t?b(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var l=(t,e,s)=>T(t,typeof e!="symbol"?e+"":e,s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("@inkweave/core"),_=require("zustand"),L=require("zustand/middleware"),h=require("react/jsx-runtime"),c=require("react"),C=require("@inkweave/react"),$={local:localStorage,session:sessionStorage};let I="local";const f=()=>$[I];class P{constructor(e){l(this,"data");l(this,"timestamp");l(this,"meta");this.data=JSON.stringify(e),this.timestamp=new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}).format(Date.now()),this.meta="autogenerated"}}const y=_.create()(L.persist((t,e)=>({storage:new Map,setStorage:(s,o,n)=>{const i=new Map(e().storage),d=[...i.get(s)||[]];d[o]=new P(n),i.set(s,d),t({storage:i})},changeFormat:s=>{I=s}}),{name:"inkStory",storage:{getItem:t=>{const e=f().getItem(t);if(!e)return null;try{const{state:s}=JSON.parse(e);return{state:{...s,storage:new Map(s.storage)}}}catch(s){return console.error("InkWeave: Failed to parse storage data:",s),null}},setItem:(t,e)=>{const s=JSON.stringify({state:{...e.state,storage:Array.from(e.state.storage.entries())}});f().setItem(t,s)},removeItem:t=>{f().removeItem(t)}}}));let v={memory_format:"local"};const E=t=>y(e=>e.storage.get(t)||null),F=(t,e)=>{const s={state:e.story.state.toJson()};e.save_label.forEach(o=>{const n=e[o];o in e&&n!==void 0&&(typeof n=="string"||typeof n=="number"||typeof n=="boolean"||Array.isArray(n))&&(s[o]=n)}),y.getState().setStorage(e.title,t,s)},O=(t,e)=>{let s=null;try{s=JSON.parse(t)}catch(o){console.error("InkWeave: Failed to parse save data:",o);return}s&&(e.story.state.LoadJson(s.state),e.clear(),e.save_label.forEach(o=>{o in e&&typeof e[o]<"u"&&o in s&&(e[o]=s[o])}),e.continue())},k=()=>{a.Patches.add(function(){y.getState().changeFormat(v.memory_format)},v)},w={save:F,load:O,show:E},M=({className:t="",fallback:e=null})=>{const s=m(p=>p.image),[o,n]=c.useState(!1),i=c.useCallback(()=>{n(!0),console.warn(`InkWeave: Failed to load image: ${s}`)},[s]),d=c.useCallback(()=>{n(!1)},[]);return s?o?e?h.jsx("div",{id:"inkweave-image",className:t,children:e}):null:h.jsx("div",{id:"inkweave-image",className:t,children:h.jsx("img",{src:s,alt:"",onError:i,onLoad:d})}):null},j=c.memo(M),m=_.create(t=>({image:"",setImage:e=>t({image:e})})),A=(t,e)=>e&&"resolveFilename"in e?e.resolveFilename(t):t,q=()=>{a.Tags.add("image",(t,e)=>{t?m.getState().setImage(A(t,e.options.fileHandler)):m.getState().setImage("")}),a.Patches.add(function(){Object.defineProperty(this,"image",{get(){return m.getState().image},set(t){m.getState().setImage(t)}}),this.save_label.push("image"),this.clears.push(()=>{this.image=""})},{})};class r{static get sound(){return this._sound}static get music(){return this._music}static get sound_handler(){return this._sound_handler}static get music_handler(){return this._music_handler}static set_music(e){this._music=new Audio(e),this._music.loop=!0,this._music_handler=()=>{var s;(s=this._music)==null||s.play()},this._music.addEventListener("canplaythrough",this._music_handler)}static set_sound(e){this._sound=new Audio(e),this._sound_handler=()=>{var s;(s=this._sound)==null||s.play()},this._sound.addEventListener("canplaythrough",this._sound_handler)}static cleanupSound(){this._sound&&(this._sound.pause(),this._sound.currentTime=0,this._sound.removeEventListener("canplaythrough",this._sound_handler),this._sound.src=""),this._sound=null,this._sound_handler=()=>{}}static cleanupMusic(){this._music&&(this._music.pause(),this._music.currentTime=0,this._music.removeEventListener("canplaythrough",this._music_handler),this._music.src=""),this._music=null,this._music_handler=()=>{}}}l(r,"_sound",null),l(r,"_music",null),l(r,"_sound_handler",()=>{}),l(r,"_music_handler",()=>{});const S=(t,e)=>e&&"resolveFilename"in e?e.resolveFilename(t):t,x=()=>{a.Tags.add("sound",(t,e)=>{t?(r.cleanupSound(),r.set_sound(S(t,e.options.fileHandler))):r.cleanupSound()}),a.Tags.add("music",(t,e)=>{t?(r.cleanupMusic(),r.set_music(S(t,e.options.fileHandler))):r.cleanupMusic()}),a.Patches.add(function(){this.audio=r,this.cleanups.push(()=>{r.cleanupSound(),r.cleanupMusic()})},{})},D=`
2
+ #inkweave-contents div,
3
+ #inkweave-choices {
4
+ opacity: 0;
5
+ animation: inkFadeIn 0.5s forwards;
6
+ animation-delay: var(--delay, 0s);
7
+ }
8
+ @keyframes inkFadeIn {
9
+ from {
10
+ opacity: 0;
11
+ }
12
+ to {
13
+ opacity: 1;
14
+ }
15
+ }
16
+ `,R={linedelay:.05},u=_.create(t=>({contentComplete:!0,last_content:"",setContentComplete:e=>t({contentComplete:e}),setLastContent:e=>{if(e.length===0){t({last_content:""});return}const s=e[e.length-1];t({last_content:s})}}));let g=null;const J=()=>{g||(g=document.createElement("style"),g.textContent=D,document.head.appendChild(g)),a.Patches.add(function(){const t=this.choose,e=this;this.choose=function(n){return e.options.linedelay!=0&&(u.getState().setContentComplete(!1),u.getState().setLastContent(e.contents)),t.call(e,n)},Object.defineProperty(this,"visibleLines",{get(){const n=u.getState().last_content;return e.contents.lastIndexOf(n)}}),Object.defineProperty(this,"choicesCanShow",{get(){return a.createSelectors(u).use.contentComplete()}});let s=null;const o=a.contentsStore.subscribe(()=>{e.options.linedelay!=0&&(s&&clearTimeout(s),s=setTimeout(()=>{u.getState().setContentComplete(!0)},(e.contents.length-e.visibleLines)*e.options.linedelay*1e3))});this.cleanups.push(()=>{o(),s&&clearTimeout(s)}),this.clears.push(()=>{e.options.linedelay!=0&&u.getState().setContentComplete(!1),u.getState().setLastContent([])})},R)},W=()=>{a.Patches.add(function(){let t=null;const e=a.choicesStore.subscribe(()=>{t&&clearTimeout(t),t=setTimeout(()=>{const s=document.querySelector("ul#inkweave-choices > li:last-child");if(s){const o=document.querySelector("#inkweave-story");o==null||o.scrollTo({top:s.offsetTop,behavior:"smooth"})}},0)});this.cleanups.push(()=>{e(),t&&clearTimeout(t)})},{})},N=["http:","https:"],B=()=>{a.Tags.add("linkopen",t=>{if(t){try{const e=new URL(t);if(!N.includes(e.protocol)){console.warn("InkWeave: Blocked unsafe URL protocol:",e.protocol);return}}catch{console.warn("InkWeave: Invalid URL:",t);return}window.open(t,"_blank","noopener,noreferrer")}})},U=({val:t,onClick:e,className:s="",children:o})=>{const n=c.useRef(null),i=parseFloat(t||"0");return c.useEffect(()=>{if(!(i<=0))return n.current=setInterval(()=>{e()},i*1e3),()=>{n.current&&clearInterval(n.current)}},[i,e]),h.jsx("a",{className:`inkweave-btn ${s}`,style:{display:"none"},children:o})},z=c.memo(U),G=()=>{a.ChoiceParser.add("auto",(t,e)=>{t.type="auto",t.val=e}),C.ChoiceComponents.register("auto",z),a.Patches.add(null,{})},H=({val:t,onClick:e,className:s="",children:o})=>{const[n,i]=c.useState(!1),d=parseFloat(t||"0"),p=()=>{n||(e(),i(!0),setTimeout(()=>{i(!1)},d*1e3))};return h.jsx("a",{className:`inkweave-btn ${s} ${n?"disabled":""}`,onClick:p,children:o})},K=c.memo(H),Q=()=>{a.ChoiceParser.add("cd",(t,e)=>{t.type="cd",t.val=e}),C.ChoiceComponents.register("cd",K),a.Patches.add(null,{})},X={autosave_enabled:!0},Y=()=>{a.Tags.add("autosave",(t,e)=>{e.options.autosave_enabled&&w.save(2,e)}),a.Patches.add(null,X)};exports.Image=j;exports.loadAudio=x;exports.loadAutoButton=G;exports.loadAutosave=Y;exports.loadCdButton=Q;exports.loadFadeEffect=J;exports.loadImage=q;exports.loadLinkopen=B;exports.loadMemory=k;exports.loadScrollafterchoice=W;exports.memory=w;exports.useStoryImage=m;
17
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/memory/storage.ts","../src/memory/index.ts","../src/image/Image.tsx","../src/image/index.ts","../src/audio/AudioController.ts","../src/audio/index.ts","../src/fadeEffect/index.ts","../src/scrollafterchoice/index.ts","../src/linkopen/index.ts","../src/autoButton/AutoButton.tsx","../src/autoButton/index.ts","../src/cdButton/CdButton.tsx","../src/cdButton/index.ts","../src/autosave/index.ts"],"sourcesContent":["import { create } from 'zustand';\nimport { persist, StorageValue } from 'zustand/middleware';\n\nconst StorageType: { [key: string]: Storage } = {\n\tlocal: localStorage,\n\tsession: sessionStorage,\n};\n\nlet type = 'local';\nconst getStorage = () => {\n\treturn StorageType[type];\n};\n\nexport interface SaveSlot {\n\tdata: string;\n\ttimestamp: string;\n\tmeta: string;\n}\n\nexport class Save implements SaveSlot {\n\tdata: string;\n\ttimestamp: string;\n\tmeta: string;\n\n\tconstructor(data: object) {\n\t\tthis.data = JSON.stringify(data);\n\t\tthis.timestamp = new Intl.DateTimeFormat(undefined, {\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t\thour: '2-digit',\n\t\t\tminute: '2-digit',\n\t\t}).format(Date.now());\n\t\tthis.meta = 'autogenerated';\n\t}\n}\n\ninterface StorageInterface {\n\tstorage: Map<string, SaveSlot[]>;\n\tsetStorage: (title: string, index: number, data: object) => void;\n\tchangeFormat: (format: string) => void;\n}\n\nconst useStorage = create<StorageInterface>()(\n\tpersist(\n\t\t(set, get) => ({\n\t\t\tstorage: new Map(),\n\t\t\tsetStorage: (title, index, data) => {\n\t\t\t\tconst newSavesMap = new Map(get().storage);\n\t\t\t\tconst file_saves = [...(newSavesMap.get(title) || [])];\n\t\t\t\tfile_saves[index] = new Save(data);\n\t\t\t\tnewSavesMap.set(title, file_saves);\n\t\t\t\tset({ storage: newSavesMap });\n\t\t\t},\n\t\t\tchangeFormat: (format) => {\n\t\t\t\ttype = format;\n\t\t\t},\n\t\t}),\n\t\t{\n\t\t\tname: 'inkStory',\n\t\t\tstorage: {\n\t\t\t\tgetItem: (name) => {\n\t\t\t\t\tconst str = getStorage().getItem(name);\n\t\t\t\t\tif (!str) return null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { state } = JSON.parse(str);\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstate: {\n\t\t\t\t\t\t\t\t...state,\n\t\t\t\t\t\t\t\tstorage: new Map(state.storage),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.error('InkWeave: Failed to parse storage data:', e);\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsetItem: (name, newValue: StorageValue<StorageInterface>) => {\n\t\t\t\t\tconst str = JSON.stringify({\n\t\t\t\t\t\tstate: {\n\t\t\t\t\t\t\t...newValue.state,\n\t\t\t\t\t\t\tstorage: Array.from(\n\t\t\t\t\t\t\t\tnewValue.state.storage.entries()\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tgetStorage().setItem(name, str);\n\t\t\t\t},\n\t\t\t\tremoveItem: (name) => {\n\t\t\t\t\tgetStorage().removeItem(name);\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t)\n);\n\nexport default useStorage;","import type { InkStory } from '@inkweave/core';\nimport { Patches } from '@inkweave/core';\nimport useStorage from './storage';\nimport type { SaveSlot } from './storage';\n\ninterface MemorySaveData {\n\tstate: string;\n\t[key: string]: string | number | boolean | string[] | undefined;\n}\n\nlet options = {\n\tmemory_format: 'local',\n};\n\nconst show = (title: string): SaveSlot[] | null => {\n\treturn useStorage((state) => state.storage.get(title) || null);\n};\n\nconst save = (index: number, ink: InkStory) => {\n\tconst saveData: MemorySaveData = {\n\t\tstate: ink.story.state.toJson(),\n\t};\n\tink.save_label.forEach((label) => {\n\t\tconst value = ink[label as keyof InkStory];\n\t\tif (label in ink && value !== undefined) {\n\t\t\tif (\n\t\t\t\ttypeof value === 'string' ||\n\t\t\t\ttypeof value === 'number' ||\n\t\t\t\ttypeof value === 'boolean' ||\n\t\t\t\tArray.isArray(value)\n\t\t\t) {\n\t\t\t\tsaveData[label] = value as string | number | boolean | string[];\n\t\t\t}\n\t\t}\n\t});\n\tuseStorage.getState().setStorage(ink.title, index, saveData);\n};\n\nconst load = (save_data: string, ink: InkStory) => {\n\tlet save: MemorySaveData | null = null;\n\ttry {\n\t\tsave = JSON.parse(save_data);\n\t} catch (e) {\n\t\tconsole.error('InkWeave: Failed to parse save data:', e);\n\t\treturn;\n\t}\n\tif (save) {\n\t\tink.story.state.LoadJson(save.state);\n\t\tink.clear();\n\t\tink.save_label.forEach((label) => {\n\t\t\tif (\n\t\t\t\tlabel in ink &&\n\t\t\t\ttypeof ink[label as keyof InkStory] !== 'undefined' &&\n\t\t\t\tlabel in save\n\t\t\t)\n\t\t\t\t(ink as Record<string, unknown>)[label] = save[label];\n\t\t});\n\t\tink.continue();\n\t}\n};\n\nconst loadMemory = () => {\n\tPatches.add(function () {\n\t\tuseStorage.getState().changeFormat(options.memory_format);\n\t}, options);\n};\n\nexport const memory = { save, load, show };\nexport type { SaveSlot };\nexport default loadMemory;","import { memo, useState, useCallback } from 'react';\nimport { useStoryImage } from './index';\n\ninterface ImageProps {\n\tclassName?: string;\n\tfallback?: React.ReactNode;\n}\n\nconst ImageComponent: React.FC<ImageProps> = ({ className = '', fallback = null }) => {\n\tconst image = useStoryImage((state) => state.image);\n\tconst [hasError, setHasError] = useState(false);\n\n\tconst handleError = useCallback(() => {\n\t\tsetHasError(true);\n\t\tconsole.warn(`InkWeave: Failed to load image: ${image}`);\n\t}, [image]);\n\n\tconst handleLoad = useCallback(() => {\n\t\tsetHasError(false);\n\t}, []);\n\n\tif (!image) return null;\n\n\tif (hasError) {\n\t\treturn fallback ? <div id=\"inkweave-image\" className={className}>{fallback}</div> : null;\n\t}\n\n\treturn (\n\t\t<div id=\"inkweave-image\" className={className}>\n\t\t\t<img src={image} alt=\"\" onError={handleError} onLoad={handleLoad} />\n\t\t</div>\n\t);\n};\n\nexport default memo(ImageComponent);","import { create } from 'zustand';\nimport { Tags, Patches, type InkStory, type FileHandler } from '@inkweave/core';\n\ndeclare module '@inkweave/core' {\n\tinterface InkStory {\n\t\timage: string;\n\t}\n}\n\ntype StoryImage = {\n\timage: string;\n\tsetImage: (image: string) => void;\n};\n\nexport const useStoryImage = create<StoryImage>((set) => ({\n\timage: '',\n\tsetImage: (image) => set({ image }),\n}));\n\nconst getPath = (path: string, fileHandler?: FileHandler) => {\n\tif (fileHandler && 'resolveFilename' in fileHandler) {\n\t\treturn (fileHandler as { resolveFilename: (f: string) => string }).resolveFilename(path);\n\t}\n\treturn path;\n};\n\nconst load = () => {\n\tTags.add('image', (val: string | null | undefined, ink: InkStory) => {\n\t\tif (val) {\n\t\t\tuseStoryImage.getState().setImage(getPath(val, ink.options.fileHandler));\n\t\t} else {\n\t\t\tuseStoryImage.getState().setImage('');\n\t\t}\n\t});\n\n\tPatches.add(function () {\n\t\tObject.defineProperty(this, 'image', {\n\t\t\tget() {\n\t\t\t\treturn useStoryImage.getState().image;\n\t\t\t},\n\n\t\t\tset(path: string) {\n\t\t\t\tuseStoryImage.getState().setImage(path);\n\t\t\t},\n\t\t});\n\t\tthis.save_label.push('image');\n\t\tthis.clears.push(() => {\n\t\t\tthis.image = '';\n\t\t});\n\t}, {});\n};\n\nexport default load;\nexport { default as Image } from './Image';","export class AudioController {\n\tprivate static _sound: HTMLAudioElement | null = null;\n\tprivate static _music: HTMLAudioElement | null = null;\n\tprivate static _sound_handler: () => void = () => {};\n\tprivate static _music_handler: () => void = () => {};\n\n\tstatic get sound() {\n\t\treturn this._sound;\n\t}\n\n\tstatic get music() {\n\t\treturn this._music;\n\t}\n\n\tstatic get sound_handler() {\n\t\treturn this._sound_handler;\n\t}\n\n\tstatic get music_handler() {\n\t\treturn this._music_handler;\n\t}\n\n\tstatic set_music(path: string) {\n\t\tthis._music = new Audio(path);\n\t\tthis._music.loop = true;\n\t\tthis._music_handler = () => {\n\t\t\tthis._music?.play();\n\t\t};\n\t\tthis._music.addEventListener('canplaythrough', this._music_handler);\n\t}\n\n\tstatic set_sound(path: string) {\n\t\tthis._sound = new Audio(path);\n\t\tthis._sound_handler = () => {\n\t\t\tthis._sound?.play();\n\t\t};\n\t\tthis._sound.addEventListener('canplaythrough', this._sound_handler);\n\t}\n\n\tstatic cleanupSound() {\n\t\tif (this._sound) {\n\t\t\tthis._sound.pause();\n\t\t\tthis._sound.currentTime = 0;\n\t\t\tthis._sound.removeEventListener(\n\t\t\t\t'canplaythrough',\n\t\t\t\tthis._sound_handler\n\t\t\t);\n\t\t\tthis._sound.src = '';\n\t\t}\n\t\tthis._sound = null;\n\t\tthis._sound_handler = () => {};\n\t}\n\n\tstatic cleanupMusic() {\n\t\tif (this._music) {\n\t\t\tthis._music.pause();\n\t\t\tthis._music.currentTime = 0;\n\t\t\tthis._music.removeEventListener(\n\t\t\t\t'canplaythrough',\n\t\t\t\tthis._music_handler\n\t\t\t);\n\t\t\tthis._music.src = '';\n\t\t}\n\t\tthis._music = null;\n\t\tthis._music_handler = () => {};\n\t}\n}","import { Tags, Patches, type InkStory, type FileHandler } from '@inkweave/core';\nimport { AudioController } from './AudioController';\n\nconst getPath = (path: string, fileHandler?: FileHandler) => {\n\tif (fileHandler && 'resolveFilename' in fileHandler) {\n\t\treturn (fileHandler as { resolveFilename: (f: string) => string }).resolveFilename(path);\n\t}\n\treturn path;\n};\n\nconst load = () => {\n\tTags.add('sound', (val: string | null | undefined, ink: InkStory) => {\n\t\tif (val) {\n\t\t\tAudioController.cleanupSound();\n\t\t\tAudioController.set_sound(getPath(val, ink.options.fileHandler));\n\t\t} else {\n\t\t\tAudioController.cleanupSound();\n\t\t}\n\t});\n\n\tTags.add('music', (val: string | null | undefined, ink: InkStory) => {\n\t\tif (val) {\n\t\t\tAudioController.cleanupMusic();\n\t\t\tAudioController.set_music(getPath(val, ink.options.fileHandler));\n\t\t} else {\n\t\t\tAudioController.cleanupMusic();\n\t\t}\n\t});\n\n\tPatches.add(function () {\n\t\tthis.audio = AudioController;\n\t\tthis.cleanups.push(() => {\n\t\t\tAudioController.cleanupSound();\n\t\t\tAudioController.cleanupMusic();\n\t\t});\n\t}, {});\n};\n\nexport default load;","import { Patches, contentsStore, createSelectors, type InkStoryContext } from '@inkweave/core';\nimport { create } from 'zustand';\n\nconst FADE_CSS = `\n#inkweave-contents div,\n#inkweave-choices {\n opacity: 0;\n animation: inkFadeIn 0.5s forwards;\n animation-delay: var(--delay, 0s);\n}\n@keyframes inkFadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n`;\n\nconst options = {\n\tlinedelay: 0.05,\n};\n\ntype ContentComplete = {\n\tcontentComplete: boolean;\n\tlast_content: string;\n\tsetContentComplete: (contentComplete: boolean) => void;\n\tsetLastContent: (contents: string[]) => void;\n};\n\nconst useContentComplete = create<ContentComplete>((set) => ({\n\tcontentComplete: true,\n\tlast_content: '',\n\tsetContentComplete: (contentComplete) => set({ contentComplete }),\n\tsetLastContent: (contents) => {\n\t\tif (contents.length === 0) {\n\t\t\tset({ last_content: '' });\n\t\t\treturn;\n\t\t}\n\t\tconst last_content = contents[contents.length - 1];\n\t\tset({ last_content });\n\t},\n}));\n\nlet styleElement: HTMLStyleElement | null = null;\n\nconst load = () => {\n\t// Inject CSS only once\n\tif (!styleElement) {\n\t\tstyleElement = document.createElement('style');\n\t\tstyleElement.textContent = FADE_CSS;\n\t\tdocument.head.appendChild(styleElement);\n\t}\n\n\tPatches.add(function (this: InkStoryContext) {\n\t\tconst originalChoose = this.choose as (index: number) => void;\n\t\tconst self = this;\n\t\tthis.choose = function (index: number) {\n\t\t\tif (self.options.linedelay != 0) {\n\t\t\t\tuseContentComplete.getState().setContentComplete(false);\n\t\t\t\tuseContentComplete.getState().setLastContent(self.contents as string[]);\n\t\t\t}\n\t\t\treturn originalChoose.call(self, index);\n\t\t};\n\t\tObject.defineProperty(this, 'visibleLines', {\n\t\t\tget() {\n\t\t\t\tconst last_content = useContentComplete.getState().last_content;\n\t\t\t\treturn (self.contents as string[]).lastIndexOf(last_content);\n\t\t\t},\n\t\t});\n\t\tObject.defineProperty(this, 'choicesCanShow', {\n\t\t\tget() {\n\t\t\t\treturn createSelectors(useContentComplete).use.contentComplete();\n\t\t\t},\n\t\t});\n\n\t\tlet timer: ReturnType<typeof setTimeout> | null = null;\n\t\tconst unsub = contentsStore.subscribe(() => {\n\t\t\tif (self.options.linedelay == 0) return;\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\tuseContentComplete.getState().setContentComplete(true);\n\t\t\t}, ((self.contents as string[]).length - (self.visibleLines as number)) * (self.options.linedelay as number) * 1000);\n\t\t});\n\n\t\tthis.cleanups.push(() => {\n\t\t\tunsub();\n\t\t\tif (timer) clearTimeout(timer);\n\t\t});\n\t\tthis.clears.push(() => {\n\t\t\tif (self.options.linedelay != 0)\n\t\t\t\tuseContentComplete.getState().setContentComplete(false);\n\t\t\tuseContentComplete.getState().setLastContent([]);\n\t\t});\n\t}, options);\n};\n\nexport default load;","import { Patches, choicesStore } from '@inkweave/core';\n\nconst load = () => {\n\tPatches.add(function () {\n\t\tlet scrollTimer: ReturnType<typeof setTimeout> | null = null;\n\t\t\n\t\tconst unsub = choicesStore.subscribe(() => {\n\t\t\tif (scrollTimer) clearTimeout(scrollTimer);\n\t\t\t\n\t\t\tscrollTimer = setTimeout(() => {\n\t\t\t\tconst lastButton = document.querySelector(\n\t\t\t\t\t'ul#inkweave-choices > li:last-child'\n\t\t\t\t) as HTMLElement;\n\t\t\t\tif (lastButton) {\n\t\t\t\t\tconst element = document.querySelector(\n\t\t\t\t\t\t'#inkweave-story'\n\t\t\t\t\t) as HTMLElement;\n\t\t\t\t\telement?.scrollTo({\n\t\t\t\t\t\ttop: lastButton.offsetTop,\n\t\t\t\t\t\tbehavior: 'smooth',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, 0);\n\t\t});\n\t\t\n\t\tthis.cleanups.push(() => {\n\t\t\tunsub();\n\t\t\tif (scrollTimer) clearTimeout(scrollTimer);\n\t\t});\n\t}, {});\n};\n\nexport default load;","import { Tags } from '@inkweave/core';\n\nconst ALLOWED_PROTOCOLS = ['http:', 'https:'];\n\nconst load = () => {\n\tTags.add('linkopen', (val: string | null | undefined) => {\n\t\tif (val) {\n\t\t\ttry {\n\t\t\t\tconst url = new URL(val);\n\t\t\t\tif (!ALLOWED_PROTOCOLS.includes(url.protocol)) {\n\t\t\t\t\tconsole.warn('InkWeave: Blocked unsafe URL protocol:', url.protocol);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tconsole.warn('InkWeave: Invalid URL:', val);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\twindow.open(val, '_blank', 'noopener,noreferrer');\n\t\t}\n\t});\n};\n\nexport default load;","import { memo, useEffect, useRef } from 'react';\nimport type { ChoiceComponentProps } from '@inkweave/react';\n\nconst AutoChoice: React.FC<ChoiceComponentProps> = ({\n\tval,\n\tonClick,\n\tclassName = '',\n\tchildren,\n}) => {\n\tconst intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\tconst cd = parseFloat(val || '0');\n\n\tuseEffect(() => {\n\t\tif (cd <= 0) return;\n\n\t\tintervalRef.current = setInterval(() => {\n\t\t\tonClick();\n\t\t}, cd * 1000);\n\n\t\treturn () => {\n\t\t\tif (intervalRef.current) {\n\t\t\t\tclearInterval(intervalRef.current);\n\t\t\t}\n\t\t};\n\t}, [cd, onClick]);\n\n\treturn (\n\t\t<a className={`inkweave-btn ${className}`} style={{ display: 'none' }}>\n\t\t\t{children}\n\t\t</a>\n\t);\n};\n\nexport default memo(AutoChoice);","import { ChoiceParser, Patches } from '@inkweave/core';\nimport { ChoiceComponents } from '@inkweave/react';\nimport AutoChoice from './AutoButton';\n\nconst load = () => {\n\tChoiceParser.add('auto', (new_choice, val) => {\n\t\tnew_choice.type = 'auto';\n\t\tnew_choice.val = val;\n\t});\n\tChoiceComponents.register('auto', AutoChoice);\n\tPatches.add(null, {});\n};\n\nexport default load;","import { memo, useState } from 'react';\nimport type { ChoiceComponentProps } from '@inkweave/react';\n\nconst CooldownChoice: React.FC<ChoiceComponentProps> = ({\n\tval,\n\tonClick,\n\tclassName = '',\n\tchildren,\n}) => {\n\tconst [isDisabled, setIsDisabled] = useState(false);\n\tconst cd = parseFloat(val || '0');\n\n\tconst handleClick = () => {\n\t\tif (isDisabled) return;\n\n\t\tonClick();\n\t\tsetIsDisabled(true);\n\n\t\tsetTimeout(() => {\n\t\t\tsetIsDisabled(false);\n\t\t}, cd * 1000);\n\t};\n\n\treturn (\n\t\t<a\n\t\t\tclassName={`inkweave-btn ${className} ${isDisabled ? 'disabled' : ''}`}\n\t\t\tonClick={handleClick}\n\t\t>\n\t\t\t{children}\n\t\t</a>\n\t);\n};\n\nexport default memo(CooldownChoice);","import { ChoiceParser, Patches } from '@inkweave/core';\nimport { ChoiceComponents } from '@inkweave/react';\nimport CooldownChoice from './CdButton';\n\nconst load = () => {\n\tChoiceParser.add('cd', (new_choice, val) => {\n\t\tnew_choice.type = 'cd';\n\t\tnew_choice.val = val;\n\t});\n\tChoiceComponents.register('cd', CooldownChoice);\n\tPatches.add(null, {});\n};\n\nexport default load;","import type { InkStory } from '@inkweave/core';\nimport { Patches, Tags } from '@inkweave/core';\nimport { memory } from '../memory';\n\nconst options = {\n\tautosave_enabled: true,\n};\n\nconst load = () => {\n\tTags.add('autosave', (_: string | null | undefined, ink: InkStory) => {\n\t\tif (ink.options.autosave_enabled) {\n\t\t\tmemory.save(2, ink);\n\t\t}\n\t});\n\n\tPatches.add(null, options);\n};\n\nexport default load;"],"names":["StorageType","type","getStorage","Save","data","__publicField","useStorage","create","persist","set","get","title","index","newSavesMap","file_saves","format","name","str","state","e","newValue","options","show","save","ink","saveData","label","value","load","save_data","loadMemory","Patches","memory","ImageComponent","className","fallback","image","useStoryImage","hasError","setHasError","useState","handleError","useCallback","handleLoad","jsx","Image","memo","getPath","path","fileHandler","Tags","val","AudioController","_a","FADE_CSS","useContentComplete","contentComplete","contents","last_content","styleElement","originalChoose","self","createSelectors","timer","unsub","contentsStore","scrollTimer","choicesStore","lastButton","element","ALLOWED_PROTOCOLS","url","AutoChoice","onClick","children","intervalRef","useRef","cd","useEffect","ChoiceParser","new_choice","ChoiceComponents","CooldownChoice","isDisabled","setIsDisabled","handleClick","_"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export { default as loadMemory, memory } from './memory';
2
+ export type { SaveSlot } from './memory';
3
+ export { default as loadImage, useStoryImage } from './image';
4
+ export { Image } from './image';
5
+ export { default as loadAudio } from './audio';
6
+ export { default as loadFadeEffect } from './fadeEffect';
7
+ export { default as loadScrollafterchoice } from './scrollafterchoice';
8
+ export { default as loadLinkopen } from './linkopen';
9
+ export { default as loadAutoButton } from './autoButton';
10
+ export { default as loadCdButton } from './cdButton';
11
+ export { default as loadAutosave } from './autosave';
package/dist/index.js ADDED
@@ -0,0 +1,342 @@
1
+ var E = Object.defineProperty;
2
+ var F = (e, t, s) => t in e ? E(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
3
+ var r = (e, t, s) => F(e, typeof t != "symbol" ? t + "" : t, s);
4
+ import { Patches as c, Tags as h, createSelectors as T, contentsStore as O, choicesStore as k, ChoiceParser as w } from "@inkweave/core";
5
+ import { create as _ } from "zustand";
6
+ import { persist as A } from "zustand/middleware";
7
+ import { jsx as m } from "react/jsx-runtime";
8
+ import { memo as y, useState as b, useCallback as S, useRef as M, useEffect as P } from "react";
9
+ import { ChoiceComponents as L } from "@inkweave/react";
10
+ const D = {
11
+ local: localStorage,
12
+ session: sessionStorage
13
+ };
14
+ let $ = "local";
15
+ const f = () => D[$];
16
+ class J {
17
+ constructor(t) {
18
+ r(this, "data");
19
+ r(this, "timestamp");
20
+ r(this, "meta");
21
+ this.data = JSON.stringify(t), this.timestamp = new Intl.DateTimeFormat(void 0, {
22
+ month: "short",
23
+ day: "numeric",
24
+ hour: "2-digit",
25
+ minute: "2-digit"
26
+ }).format(Date.now()), this.meta = "autogenerated";
27
+ }
28
+ }
29
+ const v = _()(
30
+ A(
31
+ (e, t) => ({
32
+ storage: /* @__PURE__ */ new Map(),
33
+ setStorage: (s, o, n) => {
34
+ const i = new Map(t().storage), u = [...i.get(s) || []];
35
+ u[o] = new J(n), i.set(s, u), e({ storage: i });
36
+ },
37
+ changeFormat: (s) => {
38
+ $ = s;
39
+ }
40
+ }),
41
+ {
42
+ name: "inkStory",
43
+ storage: {
44
+ getItem: (e) => {
45
+ const t = f().getItem(e);
46
+ if (!t) return null;
47
+ try {
48
+ const { state: s } = JSON.parse(t);
49
+ return {
50
+ state: {
51
+ ...s,
52
+ storage: new Map(s.storage)
53
+ }
54
+ };
55
+ } catch (s) {
56
+ return console.error("InkWeave: Failed to parse storage data:", s), null;
57
+ }
58
+ },
59
+ setItem: (e, t) => {
60
+ const s = JSON.stringify({
61
+ state: {
62
+ ...t.state,
63
+ storage: Array.from(
64
+ t.state.storage.entries()
65
+ )
66
+ }
67
+ });
68
+ f().setItem(e, s);
69
+ },
70
+ removeItem: (e) => {
71
+ f().removeItem(e);
72
+ }
73
+ }
74
+ }
75
+ )
76
+ );
77
+ let C = {
78
+ memory_format: "local"
79
+ };
80
+ const R = (e) => v((t) => t.storage.get(e) || null), W = (e, t) => {
81
+ const s = {
82
+ state: t.story.state.toJson()
83
+ };
84
+ t.save_label.forEach((o) => {
85
+ const n = t[o];
86
+ o in t && n !== void 0 && (typeof n == "string" || typeof n == "number" || typeof n == "boolean" || Array.isArray(n)) && (s[o] = n);
87
+ }), v.getState().setStorage(t.title, e, s);
88
+ }, N = (e, t) => {
89
+ let s = null;
90
+ try {
91
+ s = JSON.parse(e);
92
+ } catch (o) {
93
+ console.error("InkWeave: Failed to parse save data:", o);
94
+ return;
95
+ }
96
+ s && (t.story.state.LoadJson(s.state), t.clear(), t.save_label.forEach((o) => {
97
+ o in t && typeof t[o] < "u" && o in s && (t[o] = s[o]);
98
+ }), t.continue());
99
+ }, nt = () => {
100
+ c.add(function() {
101
+ v.getState().changeFormat(C.memory_format);
102
+ }, C);
103
+ }, j = { save: W, load: N, show: R }, x = ({ className: e = "", fallback: t = null }) => {
104
+ const s = d((g) => g.image), [o, n] = b(!1), i = S(() => {
105
+ n(!0), console.warn(`InkWeave: Failed to load image: ${s}`);
106
+ }, [s]), u = S(() => {
107
+ n(!1);
108
+ }, []);
109
+ return s ? o ? t ? /* @__PURE__ */ m("div", { id: "inkweave-image", className: e, children: t }) : null : /* @__PURE__ */ m("div", { id: "inkweave-image", className: e, children: /* @__PURE__ */ m("img", { src: s, alt: "", onError: i, onLoad: u }) }) : null;
110
+ }, at = y(x), d = _((e) => ({
111
+ image: "",
112
+ setImage: (t) => e({ image: t })
113
+ })), B = (e, t) => t && "resolveFilename" in t ? t.resolveFilename(e) : e, it = () => {
114
+ h.add("image", (e, t) => {
115
+ e ? d.getState().setImage(B(e, t.options.fileHandler)) : d.getState().setImage("");
116
+ }), c.add(function() {
117
+ Object.defineProperty(this, "image", {
118
+ get() {
119
+ return d.getState().image;
120
+ },
121
+ set(e) {
122
+ d.getState().setImage(e);
123
+ }
124
+ }), this.save_label.push("image"), this.clears.push(() => {
125
+ this.image = "";
126
+ });
127
+ }, {});
128
+ };
129
+ class a {
130
+ static get sound() {
131
+ return this._sound;
132
+ }
133
+ static get music() {
134
+ return this._music;
135
+ }
136
+ static get sound_handler() {
137
+ return this._sound_handler;
138
+ }
139
+ static get music_handler() {
140
+ return this._music_handler;
141
+ }
142
+ static set_music(t) {
143
+ this._music = new Audio(t), this._music.loop = !0, this._music_handler = () => {
144
+ var s;
145
+ (s = this._music) == null || s.play();
146
+ }, this._music.addEventListener("canplaythrough", this._music_handler);
147
+ }
148
+ static set_sound(t) {
149
+ this._sound = new Audio(t), this._sound_handler = () => {
150
+ var s;
151
+ (s = this._sound) == null || s.play();
152
+ }, this._sound.addEventListener("canplaythrough", this._sound_handler);
153
+ }
154
+ static cleanupSound() {
155
+ this._sound && (this._sound.pause(), this._sound.currentTime = 0, this._sound.removeEventListener(
156
+ "canplaythrough",
157
+ this._sound_handler
158
+ ), this._sound.src = ""), this._sound = null, this._sound_handler = () => {
159
+ };
160
+ }
161
+ static cleanupMusic() {
162
+ this._music && (this._music.pause(), this._music.currentTime = 0, this._music.removeEventListener(
163
+ "canplaythrough",
164
+ this._music_handler
165
+ ), this._music.src = ""), this._music = null, this._music_handler = () => {
166
+ };
167
+ }
168
+ }
169
+ r(a, "_sound", null), r(a, "_music", null), r(a, "_sound_handler", () => {
170
+ }), r(a, "_music_handler", () => {
171
+ });
172
+ const I = (e, t) => t && "resolveFilename" in t ? t.resolveFilename(e) : e, rt = () => {
173
+ h.add("sound", (e, t) => {
174
+ e ? (a.cleanupSound(), a.set_sound(I(e, t.options.fileHandler))) : a.cleanupSound();
175
+ }), h.add("music", (e, t) => {
176
+ e ? (a.cleanupMusic(), a.set_music(I(e, t.options.fileHandler))) : a.cleanupMusic();
177
+ }), c.add(function() {
178
+ this.audio = a, this.cleanups.push(() => {
179
+ a.cleanupSound(), a.cleanupMusic();
180
+ });
181
+ }, {});
182
+ }, U = `
183
+ #inkweave-contents div,
184
+ #inkweave-choices {
185
+ opacity: 0;
186
+ animation: inkFadeIn 0.5s forwards;
187
+ animation-delay: var(--delay, 0s);
188
+ }
189
+ @keyframes inkFadeIn {
190
+ from {
191
+ opacity: 0;
192
+ }
193
+ to {
194
+ opacity: 1;
195
+ }
196
+ }
197
+ `, q = {
198
+ linedelay: 0.05
199
+ }, l = _((e) => ({
200
+ contentComplete: !0,
201
+ last_content: "",
202
+ setContentComplete: (t) => e({ contentComplete: t }),
203
+ setLastContent: (t) => {
204
+ if (t.length === 0) {
205
+ e({ last_content: "" });
206
+ return;
207
+ }
208
+ const s = t[t.length - 1];
209
+ e({ last_content: s });
210
+ }
211
+ }));
212
+ let p = null;
213
+ const ct = () => {
214
+ p || (p = document.createElement("style"), p.textContent = U, document.head.appendChild(p)), c.add(function() {
215
+ const e = this.choose, t = this;
216
+ this.choose = function(n) {
217
+ return t.options.linedelay != 0 && (l.getState().setContentComplete(!1), l.getState().setLastContent(t.contents)), e.call(t, n);
218
+ }, Object.defineProperty(this, "visibleLines", {
219
+ get() {
220
+ const n = l.getState().last_content;
221
+ return t.contents.lastIndexOf(n);
222
+ }
223
+ }), Object.defineProperty(this, "choicesCanShow", {
224
+ get() {
225
+ return T(l).use.contentComplete();
226
+ }
227
+ });
228
+ let s = null;
229
+ const o = O.subscribe(() => {
230
+ t.options.linedelay != 0 && (s && clearTimeout(s), s = setTimeout(() => {
231
+ l.getState().setContentComplete(!0);
232
+ }, (t.contents.length - t.visibleLines) * t.options.linedelay * 1e3));
233
+ });
234
+ this.cleanups.push(() => {
235
+ o(), s && clearTimeout(s);
236
+ }), this.clears.push(() => {
237
+ t.options.linedelay != 0 && l.getState().setContentComplete(!1), l.getState().setLastContent([]);
238
+ });
239
+ }, q);
240
+ }, lt = () => {
241
+ c.add(function() {
242
+ let e = null;
243
+ const t = k.subscribe(() => {
244
+ e && clearTimeout(e), e = setTimeout(() => {
245
+ const s = document.querySelector(
246
+ "ul#inkweave-choices > li:last-child"
247
+ );
248
+ if (s) {
249
+ const o = document.querySelector(
250
+ "#inkweave-story"
251
+ );
252
+ o == null || o.scrollTo({
253
+ top: s.offsetTop,
254
+ behavior: "smooth"
255
+ });
256
+ }
257
+ }, 0);
258
+ });
259
+ this.cleanups.push(() => {
260
+ t(), e && clearTimeout(e);
261
+ });
262
+ }, {});
263
+ }, z = ["http:", "https:"], ut = () => {
264
+ h.add("linkopen", (e) => {
265
+ if (e) {
266
+ try {
267
+ const t = new URL(e);
268
+ if (!z.includes(t.protocol)) {
269
+ console.warn("InkWeave: Blocked unsafe URL protocol:", t.protocol);
270
+ return;
271
+ }
272
+ } catch {
273
+ console.warn("InkWeave: Invalid URL:", e);
274
+ return;
275
+ }
276
+ window.open(e, "_blank", "noopener,noreferrer");
277
+ }
278
+ });
279
+ }, G = ({
280
+ val: e,
281
+ onClick: t,
282
+ className: s = "",
283
+ children: o
284
+ }) => {
285
+ const n = M(null), i = parseFloat(e || "0");
286
+ return P(() => {
287
+ if (!(i <= 0))
288
+ return n.current = setInterval(() => {
289
+ t();
290
+ }, i * 1e3), () => {
291
+ n.current && clearInterval(n.current);
292
+ };
293
+ }, [i, t]), /* @__PURE__ */ m("a", { className: `inkweave-btn ${s}`, style: { display: "none" }, children: o });
294
+ }, H = y(G), dt = () => {
295
+ w.add("auto", (e, t) => {
296
+ e.type = "auto", e.val = t;
297
+ }), L.register("auto", H), c.add(null, {});
298
+ }, K = ({
299
+ val: e,
300
+ onClick: t,
301
+ className: s = "",
302
+ children: o
303
+ }) => {
304
+ const [n, i] = b(!1), u = parseFloat(e || "0"), g = () => {
305
+ n || (t(), i(!0), setTimeout(() => {
306
+ i(!1);
307
+ }, u * 1e3));
308
+ };
309
+ return /* @__PURE__ */ m(
310
+ "a",
311
+ {
312
+ className: `inkweave-btn ${s} ${n ? "disabled" : ""}`,
313
+ onClick: g,
314
+ children: o
315
+ }
316
+ );
317
+ }, Q = y(K), mt = () => {
318
+ w.add("cd", (e, t) => {
319
+ e.type = "cd", e.val = t;
320
+ }), L.register("cd", Q), c.add(null, {});
321
+ }, X = {
322
+ autosave_enabled: !0
323
+ }, ht = () => {
324
+ h.add("autosave", (e, t) => {
325
+ t.options.autosave_enabled && j.save(2, t);
326
+ }), c.add(null, X);
327
+ };
328
+ export {
329
+ at as Image,
330
+ rt as loadAudio,
331
+ dt as loadAutoButton,
332
+ ht as loadAutosave,
333
+ mt as loadCdButton,
334
+ ct as loadFadeEffect,
335
+ it as loadImage,
336
+ ut as loadLinkopen,
337
+ nt as loadMemory,
338
+ lt as loadScrollafterchoice,
339
+ j as memory,
340
+ d as useStoryImage
341
+ };
342
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/memory/storage.ts","../src/memory/index.ts","../src/image/Image.tsx","../src/image/index.ts","../src/audio/AudioController.ts","../src/audio/index.ts","../src/fadeEffect/index.ts","../src/scrollafterchoice/index.ts","../src/linkopen/index.ts","../src/autoButton/AutoButton.tsx","../src/autoButton/index.ts","../src/cdButton/CdButton.tsx","../src/cdButton/index.ts","../src/autosave/index.ts"],"sourcesContent":["import { create } from 'zustand';\nimport { persist, StorageValue } from 'zustand/middleware';\n\nconst StorageType: { [key: string]: Storage } = {\n\tlocal: localStorage,\n\tsession: sessionStorage,\n};\n\nlet type = 'local';\nconst getStorage = () => {\n\treturn StorageType[type];\n};\n\nexport interface SaveSlot {\n\tdata: string;\n\ttimestamp: string;\n\tmeta: string;\n}\n\nexport class Save implements SaveSlot {\n\tdata: string;\n\ttimestamp: string;\n\tmeta: string;\n\n\tconstructor(data: object) {\n\t\tthis.data = JSON.stringify(data);\n\t\tthis.timestamp = new Intl.DateTimeFormat(undefined, {\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t\thour: '2-digit',\n\t\t\tminute: '2-digit',\n\t\t}).format(Date.now());\n\t\tthis.meta = 'autogenerated';\n\t}\n}\n\ninterface StorageInterface {\n\tstorage: Map<string, SaveSlot[]>;\n\tsetStorage: (title: string, index: number, data: object) => void;\n\tchangeFormat: (format: string) => void;\n}\n\nconst useStorage = create<StorageInterface>()(\n\tpersist(\n\t\t(set, get) => ({\n\t\t\tstorage: new Map(),\n\t\t\tsetStorage: (title, index, data) => {\n\t\t\t\tconst newSavesMap = new Map(get().storage);\n\t\t\t\tconst file_saves = [...(newSavesMap.get(title) || [])];\n\t\t\t\tfile_saves[index] = new Save(data);\n\t\t\t\tnewSavesMap.set(title, file_saves);\n\t\t\t\tset({ storage: newSavesMap });\n\t\t\t},\n\t\t\tchangeFormat: (format) => {\n\t\t\t\ttype = format;\n\t\t\t},\n\t\t}),\n\t\t{\n\t\t\tname: 'inkStory',\n\t\t\tstorage: {\n\t\t\t\tgetItem: (name) => {\n\t\t\t\t\tconst str = getStorage().getItem(name);\n\t\t\t\t\tif (!str) return null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { state } = JSON.parse(str);\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstate: {\n\t\t\t\t\t\t\t\t...state,\n\t\t\t\t\t\t\t\tstorage: new Map(state.storage),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.error('InkWeave: Failed to parse storage data:', e);\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsetItem: (name, newValue: StorageValue<StorageInterface>) => {\n\t\t\t\t\tconst str = JSON.stringify({\n\t\t\t\t\t\tstate: {\n\t\t\t\t\t\t\t...newValue.state,\n\t\t\t\t\t\t\tstorage: Array.from(\n\t\t\t\t\t\t\t\tnewValue.state.storage.entries()\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tgetStorage().setItem(name, str);\n\t\t\t\t},\n\t\t\t\tremoveItem: (name) => {\n\t\t\t\t\tgetStorage().removeItem(name);\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t)\n);\n\nexport default useStorage;","import type { InkStory } from '@inkweave/core';\nimport { Patches } from '@inkweave/core';\nimport useStorage from './storage';\nimport type { SaveSlot } from './storage';\n\ninterface MemorySaveData {\n\tstate: string;\n\t[key: string]: string | number | boolean | string[] | undefined;\n}\n\nlet options = {\n\tmemory_format: 'local',\n};\n\nconst show = (title: string): SaveSlot[] | null => {\n\treturn useStorage((state) => state.storage.get(title) || null);\n};\n\nconst save = (index: number, ink: InkStory) => {\n\tconst saveData: MemorySaveData = {\n\t\tstate: ink.story.state.toJson(),\n\t};\n\tink.save_label.forEach((label) => {\n\t\tconst value = ink[label as keyof InkStory];\n\t\tif (label in ink && value !== undefined) {\n\t\t\tif (\n\t\t\t\ttypeof value === 'string' ||\n\t\t\t\ttypeof value === 'number' ||\n\t\t\t\ttypeof value === 'boolean' ||\n\t\t\t\tArray.isArray(value)\n\t\t\t) {\n\t\t\t\tsaveData[label] = value as string | number | boolean | string[];\n\t\t\t}\n\t\t}\n\t});\n\tuseStorage.getState().setStorage(ink.title, index, saveData);\n};\n\nconst load = (save_data: string, ink: InkStory) => {\n\tlet save: MemorySaveData | null = null;\n\ttry {\n\t\tsave = JSON.parse(save_data);\n\t} catch (e) {\n\t\tconsole.error('InkWeave: Failed to parse save data:', e);\n\t\treturn;\n\t}\n\tif (save) {\n\t\tink.story.state.LoadJson(save.state);\n\t\tink.clear();\n\t\tink.save_label.forEach((label) => {\n\t\t\tif (\n\t\t\t\tlabel in ink &&\n\t\t\t\ttypeof ink[label as keyof InkStory] !== 'undefined' &&\n\t\t\t\tlabel in save\n\t\t\t)\n\t\t\t\t(ink as Record<string, unknown>)[label] = save[label];\n\t\t});\n\t\tink.continue();\n\t}\n};\n\nconst loadMemory = () => {\n\tPatches.add(function () {\n\t\tuseStorage.getState().changeFormat(options.memory_format);\n\t}, options);\n};\n\nexport const memory = { save, load, show };\nexport type { SaveSlot };\nexport default loadMemory;","import { memo, useState, useCallback } from 'react';\nimport { useStoryImage } from './index';\n\ninterface ImageProps {\n\tclassName?: string;\n\tfallback?: React.ReactNode;\n}\n\nconst ImageComponent: React.FC<ImageProps> = ({ className = '', fallback = null }) => {\n\tconst image = useStoryImage((state) => state.image);\n\tconst [hasError, setHasError] = useState(false);\n\n\tconst handleError = useCallback(() => {\n\t\tsetHasError(true);\n\t\tconsole.warn(`InkWeave: Failed to load image: ${image}`);\n\t}, [image]);\n\n\tconst handleLoad = useCallback(() => {\n\t\tsetHasError(false);\n\t}, []);\n\n\tif (!image) return null;\n\n\tif (hasError) {\n\t\treturn fallback ? <div id=\"inkweave-image\" className={className}>{fallback}</div> : null;\n\t}\n\n\treturn (\n\t\t<div id=\"inkweave-image\" className={className}>\n\t\t\t<img src={image} alt=\"\" onError={handleError} onLoad={handleLoad} />\n\t\t</div>\n\t);\n};\n\nexport default memo(ImageComponent);","import { create } from 'zustand';\nimport { Tags, Patches, type InkStory, type FileHandler } from '@inkweave/core';\n\ndeclare module '@inkweave/core' {\n\tinterface InkStory {\n\t\timage: string;\n\t}\n}\n\ntype StoryImage = {\n\timage: string;\n\tsetImage: (image: string) => void;\n};\n\nexport const useStoryImage = create<StoryImage>((set) => ({\n\timage: '',\n\tsetImage: (image) => set({ image }),\n}));\n\nconst getPath = (path: string, fileHandler?: FileHandler) => {\n\tif (fileHandler && 'resolveFilename' in fileHandler) {\n\t\treturn (fileHandler as { resolveFilename: (f: string) => string }).resolveFilename(path);\n\t}\n\treturn path;\n};\n\nconst load = () => {\n\tTags.add('image', (val: string | null | undefined, ink: InkStory) => {\n\t\tif (val) {\n\t\t\tuseStoryImage.getState().setImage(getPath(val, ink.options.fileHandler));\n\t\t} else {\n\t\t\tuseStoryImage.getState().setImage('');\n\t\t}\n\t});\n\n\tPatches.add(function () {\n\t\tObject.defineProperty(this, 'image', {\n\t\t\tget() {\n\t\t\t\treturn useStoryImage.getState().image;\n\t\t\t},\n\n\t\t\tset(path: string) {\n\t\t\t\tuseStoryImage.getState().setImage(path);\n\t\t\t},\n\t\t});\n\t\tthis.save_label.push('image');\n\t\tthis.clears.push(() => {\n\t\t\tthis.image = '';\n\t\t});\n\t}, {});\n};\n\nexport default load;\nexport { default as Image } from './Image';","export class AudioController {\n\tprivate static _sound: HTMLAudioElement | null = null;\n\tprivate static _music: HTMLAudioElement | null = null;\n\tprivate static _sound_handler: () => void = () => {};\n\tprivate static _music_handler: () => void = () => {};\n\n\tstatic get sound() {\n\t\treturn this._sound;\n\t}\n\n\tstatic get music() {\n\t\treturn this._music;\n\t}\n\n\tstatic get sound_handler() {\n\t\treturn this._sound_handler;\n\t}\n\n\tstatic get music_handler() {\n\t\treturn this._music_handler;\n\t}\n\n\tstatic set_music(path: string) {\n\t\tthis._music = new Audio(path);\n\t\tthis._music.loop = true;\n\t\tthis._music_handler = () => {\n\t\t\tthis._music?.play();\n\t\t};\n\t\tthis._music.addEventListener('canplaythrough', this._music_handler);\n\t}\n\n\tstatic set_sound(path: string) {\n\t\tthis._sound = new Audio(path);\n\t\tthis._sound_handler = () => {\n\t\t\tthis._sound?.play();\n\t\t};\n\t\tthis._sound.addEventListener('canplaythrough', this._sound_handler);\n\t}\n\n\tstatic cleanupSound() {\n\t\tif (this._sound) {\n\t\t\tthis._sound.pause();\n\t\t\tthis._sound.currentTime = 0;\n\t\t\tthis._sound.removeEventListener(\n\t\t\t\t'canplaythrough',\n\t\t\t\tthis._sound_handler\n\t\t\t);\n\t\t\tthis._sound.src = '';\n\t\t}\n\t\tthis._sound = null;\n\t\tthis._sound_handler = () => {};\n\t}\n\n\tstatic cleanupMusic() {\n\t\tif (this._music) {\n\t\t\tthis._music.pause();\n\t\t\tthis._music.currentTime = 0;\n\t\t\tthis._music.removeEventListener(\n\t\t\t\t'canplaythrough',\n\t\t\t\tthis._music_handler\n\t\t\t);\n\t\t\tthis._music.src = '';\n\t\t}\n\t\tthis._music = null;\n\t\tthis._music_handler = () => {};\n\t}\n}","import { Tags, Patches, type InkStory, type FileHandler } from '@inkweave/core';\nimport { AudioController } from './AudioController';\n\nconst getPath = (path: string, fileHandler?: FileHandler) => {\n\tif (fileHandler && 'resolveFilename' in fileHandler) {\n\t\treturn (fileHandler as { resolveFilename: (f: string) => string }).resolveFilename(path);\n\t}\n\treturn path;\n};\n\nconst load = () => {\n\tTags.add('sound', (val: string | null | undefined, ink: InkStory) => {\n\t\tif (val) {\n\t\t\tAudioController.cleanupSound();\n\t\t\tAudioController.set_sound(getPath(val, ink.options.fileHandler));\n\t\t} else {\n\t\t\tAudioController.cleanupSound();\n\t\t}\n\t});\n\n\tTags.add('music', (val: string | null | undefined, ink: InkStory) => {\n\t\tif (val) {\n\t\t\tAudioController.cleanupMusic();\n\t\t\tAudioController.set_music(getPath(val, ink.options.fileHandler));\n\t\t} else {\n\t\t\tAudioController.cleanupMusic();\n\t\t}\n\t});\n\n\tPatches.add(function () {\n\t\tthis.audio = AudioController;\n\t\tthis.cleanups.push(() => {\n\t\t\tAudioController.cleanupSound();\n\t\t\tAudioController.cleanupMusic();\n\t\t});\n\t}, {});\n};\n\nexport default load;","import { Patches, contentsStore, createSelectors, type InkStoryContext } from '@inkweave/core';\nimport { create } from 'zustand';\n\nconst FADE_CSS = `\n#inkweave-contents div,\n#inkweave-choices {\n opacity: 0;\n animation: inkFadeIn 0.5s forwards;\n animation-delay: var(--delay, 0s);\n}\n@keyframes inkFadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n`;\n\nconst options = {\n\tlinedelay: 0.05,\n};\n\ntype ContentComplete = {\n\tcontentComplete: boolean;\n\tlast_content: string;\n\tsetContentComplete: (contentComplete: boolean) => void;\n\tsetLastContent: (contents: string[]) => void;\n};\n\nconst useContentComplete = create<ContentComplete>((set) => ({\n\tcontentComplete: true,\n\tlast_content: '',\n\tsetContentComplete: (contentComplete) => set({ contentComplete }),\n\tsetLastContent: (contents) => {\n\t\tif (contents.length === 0) {\n\t\t\tset({ last_content: '' });\n\t\t\treturn;\n\t\t}\n\t\tconst last_content = contents[contents.length - 1];\n\t\tset({ last_content });\n\t},\n}));\n\nlet styleElement: HTMLStyleElement | null = null;\n\nconst load = () => {\n\t// Inject CSS only once\n\tif (!styleElement) {\n\t\tstyleElement = document.createElement('style');\n\t\tstyleElement.textContent = FADE_CSS;\n\t\tdocument.head.appendChild(styleElement);\n\t}\n\n\tPatches.add(function (this: InkStoryContext) {\n\t\tconst originalChoose = this.choose as (index: number) => void;\n\t\tconst self = this;\n\t\tthis.choose = function (index: number) {\n\t\t\tif (self.options.linedelay != 0) {\n\t\t\t\tuseContentComplete.getState().setContentComplete(false);\n\t\t\t\tuseContentComplete.getState().setLastContent(self.contents as string[]);\n\t\t\t}\n\t\t\treturn originalChoose.call(self, index);\n\t\t};\n\t\tObject.defineProperty(this, 'visibleLines', {\n\t\t\tget() {\n\t\t\t\tconst last_content = useContentComplete.getState().last_content;\n\t\t\t\treturn (self.contents as string[]).lastIndexOf(last_content);\n\t\t\t},\n\t\t});\n\t\tObject.defineProperty(this, 'choicesCanShow', {\n\t\t\tget() {\n\t\t\t\treturn createSelectors(useContentComplete).use.contentComplete();\n\t\t\t},\n\t\t});\n\n\t\tlet timer: ReturnType<typeof setTimeout> | null = null;\n\t\tconst unsub = contentsStore.subscribe(() => {\n\t\t\tif (self.options.linedelay == 0) return;\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\tuseContentComplete.getState().setContentComplete(true);\n\t\t\t}, ((self.contents as string[]).length - (self.visibleLines as number)) * (self.options.linedelay as number) * 1000);\n\t\t});\n\n\t\tthis.cleanups.push(() => {\n\t\t\tunsub();\n\t\t\tif (timer) clearTimeout(timer);\n\t\t});\n\t\tthis.clears.push(() => {\n\t\t\tif (self.options.linedelay != 0)\n\t\t\t\tuseContentComplete.getState().setContentComplete(false);\n\t\t\tuseContentComplete.getState().setLastContent([]);\n\t\t});\n\t}, options);\n};\n\nexport default load;","import { Patches, choicesStore } from '@inkweave/core';\n\nconst load = () => {\n\tPatches.add(function () {\n\t\tlet scrollTimer: ReturnType<typeof setTimeout> | null = null;\n\t\t\n\t\tconst unsub = choicesStore.subscribe(() => {\n\t\t\tif (scrollTimer) clearTimeout(scrollTimer);\n\t\t\t\n\t\t\tscrollTimer = setTimeout(() => {\n\t\t\t\tconst lastButton = document.querySelector(\n\t\t\t\t\t'ul#inkweave-choices > li:last-child'\n\t\t\t\t) as HTMLElement;\n\t\t\t\tif (lastButton) {\n\t\t\t\t\tconst element = document.querySelector(\n\t\t\t\t\t\t'#inkweave-story'\n\t\t\t\t\t) as HTMLElement;\n\t\t\t\t\telement?.scrollTo({\n\t\t\t\t\t\ttop: lastButton.offsetTop,\n\t\t\t\t\t\tbehavior: 'smooth',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, 0);\n\t\t});\n\t\t\n\t\tthis.cleanups.push(() => {\n\t\t\tunsub();\n\t\t\tif (scrollTimer) clearTimeout(scrollTimer);\n\t\t});\n\t}, {});\n};\n\nexport default load;","import { Tags } from '@inkweave/core';\n\nconst ALLOWED_PROTOCOLS = ['http:', 'https:'];\n\nconst load = () => {\n\tTags.add('linkopen', (val: string | null | undefined) => {\n\t\tif (val) {\n\t\t\ttry {\n\t\t\t\tconst url = new URL(val);\n\t\t\t\tif (!ALLOWED_PROTOCOLS.includes(url.protocol)) {\n\t\t\t\t\tconsole.warn('InkWeave: Blocked unsafe URL protocol:', url.protocol);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tconsole.warn('InkWeave: Invalid URL:', val);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\twindow.open(val, '_blank', 'noopener,noreferrer');\n\t\t}\n\t});\n};\n\nexport default load;","import { memo, useEffect, useRef } from 'react';\nimport type { ChoiceComponentProps } from '@inkweave/react';\n\nconst AutoChoice: React.FC<ChoiceComponentProps> = ({\n\tval,\n\tonClick,\n\tclassName = '',\n\tchildren,\n}) => {\n\tconst intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\tconst cd = parseFloat(val || '0');\n\n\tuseEffect(() => {\n\t\tif (cd <= 0) return;\n\n\t\tintervalRef.current = setInterval(() => {\n\t\t\tonClick();\n\t\t}, cd * 1000);\n\n\t\treturn () => {\n\t\t\tif (intervalRef.current) {\n\t\t\t\tclearInterval(intervalRef.current);\n\t\t\t}\n\t\t};\n\t}, [cd, onClick]);\n\n\treturn (\n\t\t<a className={`inkweave-btn ${className}`} style={{ display: 'none' }}>\n\t\t\t{children}\n\t\t</a>\n\t);\n};\n\nexport default memo(AutoChoice);","import { ChoiceParser, Patches } from '@inkweave/core';\nimport { ChoiceComponents } from '@inkweave/react';\nimport AutoChoice from './AutoButton';\n\nconst load = () => {\n\tChoiceParser.add('auto', (new_choice, val) => {\n\t\tnew_choice.type = 'auto';\n\t\tnew_choice.val = val;\n\t});\n\tChoiceComponents.register('auto', AutoChoice);\n\tPatches.add(null, {});\n};\n\nexport default load;","import { memo, useState } from 'react';\nimport type { ChoiceComponentProps } from '@inkweave/react';\n\nconst CooldownChoice: React.FC<ChoiceComponentProps> = ({\n\tval,\n\tonClick,\n\tclassName = '',\n\tchildren,\n}) => {\n\tconst [isDisabled, setIsDisabled] = useState(false);\n\tconst cd = parseFloat(val || '0');\n\n\tconst handleClick = () => {\n\t\tif (isDisabled) return;\n\n\t\tonClick();\n\t\tsetIsDisabled(true);\n\n\t\tsetTimeout(() => {\n\t\t\tsetIsDisabled(false);\n\t\t}, cd * 1000);\n\t};\n\n\treturn (\n\t\t<a\n\t\t\tclassName={`inkweave-btn ${className} ${isDisabled ? 'disabled' : ''}`}\n\t\t\tonClick={handleClick}\n\t\t>\n\t\t\t{children}\n\t\t</a>\n\t);\n};\n\nexport default memo(CooldownChoice);","import { ChoiceParser, Patches } from '@inkweave/core';\nimport { ChoiceComponents } from '@inkweave/react';\nimport CooldownChoice from './CdButton';\n\nconst load = () => {\n\tChoiceParser.add('cd', (new_choice, val) => {\n\t\tnew_choice.type = 'cd';\n\t\tnew_choice.val = val;\n\t});\n\tChoiceComponents.register('cd', CooldownChoice);\n\tPatches.add(null, {});\n};\n\nexport default load;","import type { InkStory } from '@inkweave/core';\nimport { Patches, Tags } from '@inkweave/core';\nimport { memory } from '../memory';\n\nconst options = {\n\tautosave_enabled: true,\n};\n\nconst load = () => {\n\tTags.add('autosave', (_: string | null | undefined, ink: InkStory) => {\n\t\tif (ink.options.autosave_enabled) {\n\t\t\tmemory.save(2, ink);\n\t\t}\n\t});\n\n\tPatches.add(null, options);\n};\n\nexport default load;"],"names":["StorageType","type","getStorage","Save","data","__publicField","useStorage","create","persist","set","get","title","index","newSavesMap","file_saves","format","name","str","state","e","newValue","options","show","save","ink","saveData","label","value","load","save_data","loadMemory","Patches","memory","ImageComponent","className","fallback","image","useStoryImage","hasError","setHasError","useState","handleError","useCallback","handleLoad","jsx","Image","memo","getPath","path","fileHandler","Tags","val","AudioController","_a","FADE_CSS","useContentComplete","contentComplete","contents","last_content","styleElement","originalChoose","self","createSelectors","timer","unsub","contentsStore","scrollTimer","choicesStore","lastButton","element","ALLOWED_PROTOCOLS","url","AutoChoice","onClick","children","intervalRef","useRef","cd","useEffect","AutoChoice$1","ChoiceParser","new_choice","ChoiceComponents","CooldownChoice","isDisabled","setIsDisabled","handleClick","CooldownChoice$1","_"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ declare const load: () => void;
2
+ export default load;
@@ -0,0 +1,10 @@
1
+ import { InkStory } from '@inkweave/core';
2
+ import { SaveSlot } from './storage';
3
+ declare const loadMemory: () => void;
4
+ export declare const memory: {
5
+ save: (index: number, ink: InkStory) => void;
6
+ load: (save_data: string, ink: InkStory) => void;
7
+ show: (title: string) => SaveSlot[] | null;
8
+ };
9
+ export type { SaveSlot };
10
+ export default loadMemory;
@@ -0,0 +1,30 @@
1
+ export interface SaveSlot {
2
+ data: string;
3
+ timestamp: string;
4
+ meta: string;
5
+ }
6
+ export declare class Save implements SaveSlot {
7
+ data: string;
8
+ timestamp: string;
9
+ meta: string;
10
+ constructor(data: object);
11
+ }
12
+ interface StorageInterface {
13
+ storage: Map<string, SaveSlot[]>;
14
+ setStorage: (title: string, index: number, data: object) => void;
15
+ changeFormat: (format: string) => void;
16
+ }
17
+ declare const useStorage: import('zustand').UseBoundStore<Omit<import('zustand').StoreApi<StorageInterface>, "setState" | "persist"> & {
18
+ setState(partial: StorageInterface | Partial<StorageInterface> | ((state: StorageInterface) => StorageInterface | Partial<StorageInterface>), replace?: false | undefined): unknown;
19
+ setState(state: StorageInterface | ((state: StorageInterface) => StorageInterface), replace: true): unknown;
20
+ persist: {
21
+ setOptions: (options: Partial<import('zustand/middleware').PersistOptions<StorageInterface, StorageInterface, unknown>>) => void;
22
+ clearStorage: () => void;
23
+ rehydrate: () => Promise<void> | void;
24
+ hasHydrated: () => boolean;
25
+ onHydrate: (fn: (state: StorageInterface) => void) => () => void;
26
+ onFinishHydration: (fn: (state: StorageInterface) => void) => () => void;
27
+ getOptions: () => Partial<import('zustand/middleware').PersistOptions<StorageInterface, StorageInterface, unknown>>;
28
+ };
29
+ }>;
30
+ export default useStorage;
@@ -0,0 +1,2 @@
1
+ declare const load: () => void;
2
+ export default load;
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@inkweave/plugins",
3
+ "version": "1.0.0",
4
+ "description": "Optional plugins for InkWeave",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc --noEmit && vite build",
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "bun test",
23
+ "test:watch": "bun test --watch"
24
+ },
25
+ "keywords": [
26
+ "ink",
27
+ "interactive-fiction",
28
+ "plugins",
29
+ "inkweave"
30
+ ],
31
+ "author": "Uglyboy",
32
+ "license": "MIT",
33
+ "peerDependencies": {
34
+ "@inkweave/core": "^1.0.0",
35
+ "@inkweave/react": "^1.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/react": "^19.0.0",
39
+ "jsdom": "^26.1.0",
40
+ "react": "^19.0.0",
41
+ "typescript": "^5.0.0",
42
+ "vite": "^6.0.0",
43
+ "vite-plugin-dts": "^4.5.4"
44
+ }
45
+ }