@verbaly/vue 0.69.1 → 0.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index.cjs +7 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -39,7 +39,9 @@ app.use(verbalyPlugin(verbaly));
|
|
|
39
39
|
</template>
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
**
|
|
42
|
+
**The plugin is optional in the browser.** With none above it, a hook reads the instance `virtual:verbaly` creates, so a single-page app can skip it and a component test renders with no wrapper. On a server it is required, since every request has its own instance.
|
|
43
|
+
|
|
44
|
+
**Keys are typed.** `useT()` checks every key and its params against your source catalog, through the types Verbaly generates (`src/verbaly.d.ts` in a Vite app, `.nuxt/verbaly.d.ts` in Nuxt): a key no catalog has does not compile. A key that comes from data, like `t(item.key)` or a variable typed as a union of keys, passes as it is, and its params are left open; declare it with `defineKeys` from `virtual:verbaly` when you want `check` to verify it exists.
|
|
43
45
|
|
|
44
46
|
Or skip the keys entirely: write the source text in place and the compiler extracts it, right in your `.vue` files (script and template):
|
|
45
47
|
|
package/dist/index.cjs
CHANGED
|
@@ -8,9 +8,14 @@ function verbalyPlugin(instance) {
|
|
|
8
8
|
app.provide(KEY, instance);
|
|
9
9
|
} };
|
|
10
10
|
}
|
|
11
|
+
const APP_INSTANCE = Symbol.for("verbaly.app");
|
|
12
|
+
function appInstance() {
|
|
13
|
+
if (typeof document === "undefined") return null;
|
|
14
|
+
return globalThis[APP_INSTANCE] ?? null;
|
|
15
|
+
}
|
|
11
16
|
function useVerbaly() {
|
|
12
|
-
const instance = (0, vue.inject)(KEY, null);
|
|
13
|
-
if (!instance) throw new Error("[verbaly] useVerbaly requires app.use(verbalyPlugin(...))");
|
|
17
|
+
const instance = (0, vue.inject)(KEY, null) ?? appInstance();
|
|
18
|
+
if (!instance) throw new Error("[verbaly] useVerbaly requires app.use(verbalyPlugin(...)): on a server, or before virtual:verbaly loads");
|
|
14
19
|
return instance;
|
|
15
20
|
}
|
|
16
21
|
function useT() {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["inject","computed","shallowRef","VOID_TAGS","defineComponent","h","Fragment","parseTags","RICH_TAGS","normalizeLink"],"sources":["../src/index.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n Fragment,\n h,\n inject,\n onScopeDispose,\n shallowRef,\n type App,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n type VNodeChild,\n type WritableComputedRef,\n} from 'vue';\nimport {\n normalizeLink,\n parseTags,\n RICH_TAGS,\n VOID_TAGS,\n type DictionaryInput,\n type Params,\n type RichLink,\n type TagNode,\n type TFunction,\n type Verbaly,\n} from 'verbaly';\n\nconst KEY: InjectionKey<Verbaly> = Symbol('verbaly');\n\nexport interface VerbalyPlugin {\n install(app: App): void;\n}\n\nexport function verbalyPlugin<D extends DictionaryInput>(instance: Verbaly<D>): VerbalyPlugin {\n return {\n install(app) {\n app.provide(KEY, instance as unknown as Verbaly);\n },\n };\n}\n\nexport function useVerbaly<D extends DictionaryInput = DictionaryInput>(): Verbaly<D> {\n const instance = inject(KEY, null);\n if (!instance) {\n throw new Error('[verbaly] useVerbaly requires app.use(verbalyPlugin(...))');\n }\n return instance as unknown as Verbaly<D>;\n}\n\n// typed by the project's catalog once verbaly.d.ts exists, by a dictionary when one is named\nexport function useT<D extends DictionaryInput = DictionaryInput>(): Verbaly<D>['t'] {\n const instance = useVerbaly<D>();\n const version = trackVersion(instance);\n const t = (first: unknown, ...rest: unknown[]): string => {\n void version.value;\n return (instance.t as unknown as (...args: unknown[]) => string)(first, ...rest);\n };\n // the reactive wrapper must keep t's full surface (react/svelte hand out instance.t directly)\n (t as unknown as Pick<TFunction, 'id'>).id = instance.t.id;\n return t as unknown as Verbaly<D>['t'];\n}\n\nexport function useLocale(): WritableComputedRef<string> {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return computed({\n get: () => {\n void version.value;\n return instance.locale;\n },\n set: (locale: string) => instance.setLocale(locale),\n });\n}\n\nfunction trackVersion<D extends DictionaryInput>(instance: Verbaly<D>): ShallowRef<number> {\n const version = shallowRef(instance.version);\n onScopeDispose(\n instance.subscribe(() => {\n version.value = instance.version;\n }),\n );\n return version;\n}\n\nconst VOID = new Set(VOID_TAGS);\n\nexport type TransComponents = Record<string, (children: VNodeChild[]) => VNodeChild>;\n\n// translated message + element interpolation\nexport const Trans = defineComponent({\n name: 'Trans',\n props: {\n id: { type: String, required: true },\n values: { type: Object as PropType<Params>, default: undefined },\n instance: { type: Object as PropType<Verbaly>, default: undefined },\n components: { type: Object as PropType<TransComponents>, default: () => ({}) },\n richTags: { type: Array as PropType<string[]>, default: undefined },\n links: { type: Object as PropType<Record<string, RichLink>>, default: () => ({}) },\n },\n setup(props) {\n const instance = props.instance ?? useVerbaly();\n const version = trackVersion(instance);\n return () => {\n void version.value;\n const text = (instance.t as unknown as (id: string, values?: Params) => string)(\n props.id,\n props.values,\n );\n return h(\n Fragment,\n toNodes(\n parseTags(text),\n props.components,\n props.links,\n new Set(props.richTags ?? RICH_TAGS),\n ),\n );\n };\n },\n});\n\n// own entries only: a tag named constructor in a message must never find the one on Object\nfunction own<T>(map: Record<string, T>, name: string): T | undefined {\n return Object.prototype.hasOwnProperty.call(map, name) ? map[name] : undefined;\n}\n\nfunction toNodes(\n nodes: TagNode[],\n components: TransComponents,\n links: Record<string, RichLink>,\n richTags: Set<string>,\n): VNodeChild[] {\n return nodes.map((node) => {\n if (typeof node === 'string') return node;\n const children = toNodes(node.children, components, links, richTags);\n const fn = own(components, node.name);\n if (fn) return fn(children);\n const link = own(links, node.name);\n if (link !== undefined) {\n return h('a', normalizeLink(link), children);\n }\n if (richTags.has(node.name)) {\n return h(node.name, null, VOID.has(node.name) ? undefined : children);\n }\n return children;\n });\n}\n\nexport type { Params, TFunction, Verbaly };\n"],"mappings":";;;;AA4BA,MAAM,MAA6B,OAAO,SAAS;AAMnD,SAAgB,cAAyC,UAAqC;CAC5F,OAAO,EACL,QAAQ,KAAK;EACX,IAAI,QAAQ,KAAK,QAA8B;CACjD,EACF;AACF;
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["inject","computed","shallowRef","VOID_TAGS","defineComponent","h","Fragment","parseTags","RICH_TAGS","normalizeLink"],"sources":["../src/index.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n Fragment,\n h,\n inject,\n onScopeDispose,\n shallowRef,\n type App,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n type VNodeChild,\n type WritableComputedRef,\n} from 'vue';\nimport {\n normalizeLink,\n parseTags,\n RICH_TAGS,\n VOID_TAGS,\n type DictionaryInput,\n type Params,\n type RichLink,\n type TagNode,\n type TFunction,\n type Verbaly,\n} from 'verbaly';\n\nconst KEY: InjectionKey<Verbaly> = Symbol('verbaly');\n\nexport interface VerbalyPlugin {\n install(app: App): void;\n}\n\nexport function verbalyPlugin<D extends DictionaryInput>(instance: Verbaly<D>): VerbalyPlugin {\n return {\n install(app) {\n app.provide(KEY, instance as unknown as Verbaly);\n },\n };\n}\n\n// what virtual:verbaly registers in a browser; a server holds one instance per request instead\nconst APP_INSTANCE = Symbol.for('verbaly.app');\n\nfunction appInstance(): Verbaly | null {\n if (typeof document === 'undefined') return null;\n return ((globalThis as Record<symbol, unknown>)[APP_INSTANCE] as Verbaly | undefined) ?? null;\n}\n\n// the plugin wins; without it, a browser or a test reads the app's own instance\nexport function useVerbaly<D extends DictionaryInput = DictionaryInput>(): Verbaly<D> {\n const instance = inject(KEY, null) ?? appInstance();\n if (!instance) {\n throw new Error(\n '[verbaly] useVerbaly requires app.use(verbalyPlugin(...)): on a server, or before virtual:verbaly loads',\n );\n }\n return instance as unknown as Verbaly<D>;\n}\n\n// typed by the project's catalog once verbaly.d.ts exists, by a dictionary when one is named\nexport function useT<D extends DictionaryInput = DictionaryInput>(): Verbaly<D>['t'] {\n const instance = useVerbaly<D>();\n const version = trackVersion(instance);\n const t = (first: unknown, ...rest: unknown[]): string => {\n void version.value;\n return (instance.t as unknown as (...args: unknown[]) => string)(first, ...rest);\n };\n // the reactive wrapper must keep t's full surface (react/svelte hand out instance.t directly)\n (t as unknown as Pick<TFunction, 'id'>).id = instance.t.id;\n return t as unknown as Verbaly<D>['t'];\n}\n\nexport function useLocale(): WritableComputedRef<string> {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return computed({\n get: () => {\n void version.value;\n return instance.locale;\n },\n set: (locale: string) => instance.setLocale(locale),\n });\n}\n\nfunction trackVersion<D extends DictionaryInput>(instance: Verbaly<D>): ShallowRef<number> {\n const version = shallowRef(instance.version);\n onScopeDispose(\n instance.subscribe(() => {\n version.value = instance.version;\n }),\n );\n return version;\n}\n\nconst VOID = new Set(VOID_TAGS);\n\nexport type TransComponents = Record<string, (children: VNodeChild[]) => VNodeChild>;\n\n// translated message + element interpolation\nexport const Trans = defineComponent({\n name: 'Trans',\n props: {\n id: { type: String, required: true },\n values: { type: Object as PropType<Params>, default: undefined },\n instance: { type: Object as PropType<Verbaly>, default: undefined },\n components: { type: Object as PropType<TransComponents>, default: () => ({}) },\n richTags: { type: Array as PropType<string[]>, default: undefined },\n links: { type: Object as PropType<Record<string, RichLink>>, default: () => ({}) },\n },\n setup(props) {\n const instance = props.instance ?? useVerbaly();\n const version = trackVersion(instance);\n return () => {\n void version.value;\n const text = (instance.t as unknown as (id: string, values?: Params) => string)(\n props.id,\n props.values,\n );\n return h(\n Fragment,\n toNodes(\n parseTags(text),\n props.components,\n props.links,\n new Set(props.richTags ?? RICH_TAGS),\n ),\n );\n };\n },\n});\n\n// own entries only: a tag named constructor in a message must never find the one on Object\nfunction own<T>(map: Record<string, T>, name: string): T | undefined {\n return Object.prototype.hasOwnProperty.call(map, name) ? map[name] : undefined;\n}\n\nfunction toNodes(\n nodes: TagNode[],\n components: TransComponents,\n links: Record<string, RichLink>,\n richTags: Set<string>,\n): VNodeChild[] {\n return nodes.map((node) => {\n if (typeof node === 'string') return node;\n const children = toNodes(node.children, components, links, richTags);\n const fn = own(components, node.name);\n if (fn) return fn(children);\n const link = own(links, node.name);\n if (link !== undefined) {\n return h('a', normalizeLink(link), children);\n }\n if (richTags.has(node.name)) {\n return h(node.name, null, VOID.has(node.name) ? undefined : children);\n }\n return children;\n });\n}\n\nexport type { Params, TFunction, Verbaly };\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -7,9 +7,14 @@ function verbalyPlugin(instance) {
|
|
|
7
7
|
app.provide(KEY, instance);
|
|
8
8
|
} };
|
|
9
9
|
}
|
|
10
|
+
const APP_INSTANCE = Symbol.for("verbaly.app");
|
|
11
|
+
function appInstance() {
|
|
12
|
+
if (typeof document === "undefined") return null;
|
|
13
|
+
return globalThis[APP_INSTANCE] ?? null;
|
|
14
|
+
}
|
|
10
15
|
function useVerbaly() {
|
|
11
|
-
const instance = inject(KEY, null);
|
|
12
|
-
if (!instance) throw new Error("[verbaly] useVerbaly requires app.use(verbalyPlugin(...))");
|
|
16
|
+
const instance = inject(KEY, null) ?? appInstance();
|
|
17
|
+
if (!instance) throw new Error("[verbaly] useVerbaly requires app.use(verbalyPlugin(...)): on a server, or before virtual:verbaly loads");
|
|
13
18
|
return instance;
|
|
14
19
|
}
|
|
15
20
|
function useT() {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n Fragment,\n h,\n inject,\n onScopeDispose,\n shallowRef,\n type App,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n type VNodeChild,\n type WritableComputedRef,\n} from 'vue';\nimport {\n normalizeLink,\n parseTags,\n RICH_TAGS,\n VOID_TAGS,\n type DictionaryInput,\n type Params,\n type RichLink,\n type TagNode,\n type TFunction,\n type Verbaly,\n} from 'verbaly';\n\nconst KEY: InjectionKey<Verbaly> = Symbol('verbaly');\n\nexport interface VerbalyPlugin {\n install(app: App): void;\n}\n\nexport function verbalyPlugin<D extends DictionaryInput>(instance: Verbaly<D>): VerbalyPlugin {\n return {\n install(app) {\n app.provide(KEY, instance as unknown as Verbaly);\n },\n };\n}\n\nexport function useVerbaly<D extends DictionaryInput = DictionaryInput>(): Verbaly<D> {\n const instance = inject(KEY, null);\n if (!instance) {\n throw new Error('[verbaly] useVerbaly requires app.use(verbalyPlugin(...))');\n }\n return instance as unknown as Verbaly<D>;\n}\n\n// typed by the project's catalog once verbaly.d.ts exists, by a dictionary when one is named\nexport function useT<D extends DictionaryInput = DictionaryInput>(): Verbaly<D>['t'] {\n const instance = useVerbaly<D>();\n const version = trackVersion(instance);\n const t = (first: unknown, ...rest: unknown[]): string => {\n void version.value;\n return (instance.t as unknown as (...args: unknown[]) => string)(first, ...rest);\n };\n // the reactive wrapper must keep t's full surface (react/svelte hand out instance.t directly)\n (t as unknown as Pick<TFunction, 'id'>).id = instance.t.id;\n return t as unknown as Verbaly<D>['t'];\n}\n\nexport function useLocale(): WritableComputedRef<string> {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return computed({\n get: () => {\n void version.value;\n return instance.locale;\n },\n set: (locale: string) => instance.setLocale(locale),\n });\n}\n\nfunction trackVersion<D extends DictionaryInput>(instance: Verbaly<D>): ShallowRef<number> {\n const version = shallowRef(instance.version);\n onScopeDispose(\n instance.subscribe(() => {\n version.value = instance.version;\n }),\n );\n return version;\n}\n\nconst VOID = new Set(VOID_TAGS);\n\nexport type TransComponents = Record<string, (children: VNodeChild[]) => VNodeChild>;\n\n// translated message + element interpolation\nexport const Trans = defineComponent({\n name: 'Trans',\n props: {\n id: { type: String, required: true },\n values: { type: Object as PropType<Params>, default: undefined },\n instance: { type: Object as PropType<Verbaly>, default: undefined },\n components: { type: Object as PropType<TransComponents>, default: () => ({}) },\n richTags: { type: Array as PropType<string[]>, default: undefined },\n links: { type: Object as PropType<Record<string, RichLink>>, default: () => ({}) },\n },\n setup(props) {\n const instance = props.instance ?? useVerbaly();\n const version = trackVersion(instance);\n return () => {\n void version.value;\n const text = (instance.t as unknown as (id: string, values?: Params) => string)(\n props.id,\n props.values,\n );\n return h(\n Fragment,\n toNodes(\n parseTags(text),\n props.components,\n props.links,\n new Set(props.richTags ?? RICH_TAGS),\n ),\n );\n };\n },\n});\n\n// own entries only: a tag named constructor in a message must never find the one on Object\nfunction own<T>(map: Record<string, T>, name: string): T | undefined {\n return Object.prototype.hasOwnProperty.call(map, name) ? map[name] : undefined;\n}\n\nfunction toNodes(\n nodes: TagNode[],\n components: TransComponents,\n links: Record<string, RichLink>,\n richTags: Set<string>,\n): VNodeChild[] {\n return nodes.map((node) => {\n if (typeof node === 'string') return node;\n const children = toNodes(node.children, components, links, richTags);\n const fn = own(components, node.name);\n if (fn) return fn(children);\n const link = own(links, node.name);\n if (link !== undefined) {\n return h('a', normalizeLink(link), children);\n }\n if (richTags.has(node.name)) {\n return h(node.name, null, VOID.has(node.name) ? undefined : children);\n }\n return children;\n });\n}\n\nexport type { Params, TFunction, Verbaly };\n"],"mappings":";;;AA4BA,MAAM,MAA6B,OAAO,SAAS;AAMnD,SAAgB,cAAyC,UAAqC;CAC5F,OAAO,EACL,QAAQ,KAAK;EACX,IAAI,QAAQ,KAAK,QAA8B;CACjD,EACF;AACF;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n Fragment,\n h,\n inject,\n onScopeDispose,\n shallowRef,\n type App,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n type VNodeChild,\n type WritableComputedRef,\n} from 'vue';\nimport {\n normalizeLink,\n parseTags,\n RICH_TAGS,\n VOID_TAGS,\n type DictionaryInput,\n type Params,\n type RichLink,\n type TagNode,\n type TFunction,\n type Verbaly,\n} from 'verbaly';\n\nconst KEY: InjectionKey<Verbaly> = Symbol('verbaly');\n\nexport interface VerbalyPlugin {\n install(app: App): void;\n}\n\nexport function verbalyPlugin<D extends DictionaryInput>(instance: Verbaly<D>): VerbalyPlugin {\n return {\n install(app) {\n app.provide(KEY, instance as unknown as Verbaly);\n },\n };\n}\n\n// what virtual:verbaly registers in a browser; a server holds one instance per request instead\nconst APP_INSTANCE = Symbol.for('verbaly.app');\n\nfunction appInstance(): Verbaly | null {\n if (typeof document === 'undefined') return null;\n return ((globalThis as Record<symbol, unknown>)[APP_INSTANCE] as Verbaly | undefined) ?? null;\n}\n\n// the plugin wins; without it, a browser or a test reads the app's own instance\nexport function useVerbaly<D extends DictionaryInput = DictionaryInput>(): Verbaly<D> {\n const instance = inject(KEY, null) ?? appInstance();\n if (!instance) {\n throw new Error(\n '[verbaly] useVerbaly requires app.use(verbalyPlugin(...)): on a server, or before virtual:verbaly loads',\n );\n }\n return instance as unknown as Verbaly<D>;\n}\n\n// typed by the project's catalog once verbaly.d.ts exists, by a dictionary when one is named\nexport function useT<D extends DictionaryInput = DictionaryInput>(): Verbaly<D>['t'] {\n const instance = useVerbaly<D>();\n const version = trackVersion(instance);\n const t = (first: unknown, ...rest: unknown[]): string => {\n void version.value;\n return (instance.t as unknown as (...args: unknown[]) => string)(first, ...rest);\n };\n // the reactive wrapper must keep t's full surface (react/svelte hand out instance.t directly)\n (t as unknown as Pick<TFunction, 'id'>).id = instance.t.id;\n return t as unknown as Verbaly<D>['t'];\n}\n\nexport function useLocale(): WritableComputedRef<string> {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return computed({\n get: () => {\n void version.value;\n return instance.locale;\n },\n set: (locale: string) => instance.setLocale(locale),\n });\n}\n\nfunction trackVersion<D extends DictionaryInput>(instance: Verbaly<D>): ShallowRef<number> {\n const version = shallowRef(instance.version);\n onScopeDispose(\n instance.subscribe(() => {\n version.value = instance.version;\n }),\n );\n return version;\n}\n\nconst VOID = new Set(VOID_TAGS);\n\nexport type TransComponents = Record<string, (children: VNodeChild[]) => VNodeChild>;\n\n// translated message + element interpolation\nexport const Trans = defineComponent({\n name: 'Trans',\n props: {\n id: { type: String, required: true },\n values: { type: Object as PropType<Params>, default: undefined },\n instance: { type: Object as PropType<Verbaly>, default: undefined },\n components: { type: Object as PropType<TransComponents>, default: () => ({}) },\n richTags: { type: Array as PropType<string[]>, default: undefined },\n links: { type: Object as PropType<Record<string, RichLink>>, default: () => ({}) },\n },\n setup(props) {\n const instance = props.instance ?? useVerbaly();\n const version = trackVersion(instance);\n return () => {\n void version.value;\n const text = (instance.t as unknown as (id: string, values?: Params) => string)(\n props.id,\n props.values,\n );\n return h(\n Fragment,\n toNodes(\n parseTags(text),\n props.components,\n props.links,\n new Set(props.richTags ?? RICH_TAGS),\n ),\n );\n };\n },\n});\n\n// own entries only: a tag named constructor in a message must never find the one on Object\nfunction own<T>(map: Record<string, T>, name: string): T | undefined {\n return Object.prototype.hasOwnProperty.call(map, name) ? map[name] : undefined;\n}\n\nfunction toNodes(\n nodes: TagNode[],\n components: TransComponents,\n links: Record<string, RichLink>,\n richTags: Set<string>,\n): VNodeChild[] {\n return nodes.map((node) => {\n if (typeof node === 'string') return node;\n const children = toNodes(node.children, components, links, richTags);\n const fn = own(components, node.name);\n if (fn) return fn(children);\n const link = own(links, node.name);\n if (link !== undefined) {\n return h('a', normalizeLink(link), children);\n }\n if (richTags.has(node.name)) {\n return h(node.name, null, VOID.has(node.name) ? undefined : children);\n }\n return children;\n });\n}\n\nexport type { Params, TFunction, Verbaly };\n"],"mappings":";;;AA4BA,MAAM,MAA6B,OAAO,SAAS;AAMnD,SAAgB,cAAyC,UAAqC;CAC5F,OAAO,EACL,QAAQ,KAAK;EACX,IAAI,QAAQ,KAAK,QAA8B;CACjD,EACF;AACF;AAGA,MAAM,eAAe,OAAO,IAAI,aAAa;AAE7C,SAAS,cAA8B;CACrC,IAAI,OAAO,aAAa,aAAa,OAAO;CAC5C,OAAS,WAAuC,iBAAyC;AAC3F;AAGA,SAAgB,aAAsE;CACpF,MAAM,WAAW,OAAO,KAAK,IAAI,KAAK,YAAY;CAClD,IAAI,CAAC,UACH,MAAM,IAAI,MACR,yGACF;CAEF,OAAO;AACT;AAGA,SAAgB,OAAqE;CACnF,MAAM,WAAW,WAAc;CAC/B,MAAM,UAAU,aAAa,QAAQ;CACrC,MAAM,KAAK,OAAgB,GAAG,SAA4B;EACxD,QAAa;EACb,OAAQ,SAAS,EAAgD,OAAO,GAAG,IAAI;CACjF;CAEA,EAAwC,KAAK,SAAS,EAAE;CACxD,OAAO;AACT;AAEA,SAAgB,YAAyC;CACvD,MAAM,WAAW,WAAW;CAC5B,MAAM,UAAU,aAAa,QAAQ;CACrC,OAAO,SAAS;EACd,WAAW;GACT,QAAa;GACb,OAAO,SAAS;EAClB;EACA,MAAM,WAAmB,SAAS,UAAU,MAAM;CACpD,CAAC;AACH;AAEA,SAAS,aAAwC,UAA0C;CACzF,MAAM,UAAU,WAAW,SAAS,OAAO;CAC3C,eACE,SAAS,gBAAgB;EACvB,QAAQ,QAAQ,SAAS;CAC3B,CAAC,CACH;CACA,OAAO;AACT;AAEA,MAAM,OAAO,IAAI,IAAI,SAAS;AAK9B,MAAa,QAAQ,gBAAgB;CACnC,MAAM;CACN,OAAO;EACL,IAAI;GAAE,MAAM;GAAQ,UAAU;EAAK;EACnC,QAAQ;GAAE,MAAM;GAA4B,SAAS,KAAA;EAAU;EAC/D,UAAU;GAAE,MAAM;GAA6B,SAAS,KAAA;EAAU;EAClE,YAAY;GAAE,MAAM;GAAqC,gBAAgB,CAAC;EAAG;EAC7E,UAAU;GAAE,MAAM;GAA6B,SAAS,KAAA;EAAU;EAClE,OAAO;GAAE,MAAM;GAA8C,gBAAgB,CAAC;EAAG;CACnF;CACA,MAAM,OAAO;EACX,MAAM,WAAW,MAAM,YAAY,WAAW;EAC9C,MAAM,UAAU,aAAa,QAAQ;EACrC,aAAa;GACX,QAAa;GACb,MAAM,OAAQ,SAAS,EACrB,MAAM,IACN,MAAM,MACR;GACA,OAAO,EACL,UACA,QACE,UAAU,IAAI,GACd,MAAM,YACN,MAAM,OACN,IAAI,IAAI,MAAM,YAAY,SAAS,CACrC,CACF;EACF;CACF;AACF,CAAC;AAGD,SAAS,IAAO,KAAwB,MAA6B;CACnE,OAAO,OAAO,UAAU,eAAe,KAAK,KAAK,IAAI,IAAI,IAAI,QAAQ,KAAA;AACvE;AAEA,SAAS,QACP,OACA,YACA,OACA,UACc;CACd,OAAO,MAAM,KAAK,SAAS;EACzB,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,MAAM,WAAW,QAAQ,KAAK,UAAU,YAAY,OAAO,QAAQ;EACnE,MAAM,KAAK,IAAI,YAAY,KAAK,IAAI;EACpC,IAAI,IAAI,OAAO,GAAG,QAAQ;EAC1B,MAAM,OAAO,IAAI,OAAO,KAAK,IAAI;EACjC,IAAI,SAAS,KAAA,GACX,OAAO,EAAE,KAAK,cAAc,IAAI,GAAG,QAAQ;EAE7C,IAAI,SAAS,IAAI,KAAK,IAAI,GACxB,OAAO,EAAE,KAAK,MAAM,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,KAAA,IAAY,QAAQ;EAEtE,OAAO;CACT,CAAC;AACH"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verbaly/vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.70.0",
|
|
4
4
|
"description": "Vue 3 bindings for Verbaly: composables over the reactive core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
"access": "public"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"verbaly": "^0.
|
|
50
|
+
"verbaly": "^0.70.0",
|
|
51
51
|
"vue": "^3.4.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"happy-dom": "^20.14.5",
|
|
55
|
-
"verbaly": "^0.
|
|
55
|
+
"verbaly": "^0.70.0",
|
|
56
56
|
"vue": "^3.5.43"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|