@yoamigo.com/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ import { UserConfig, Plugin } from 'vite';
2
+
3
+ /**
4
+ * YoAmigo Vite Plugin
5
+ *
6
+ * Handles all the build-time configuration for YoAmigo templates:
7
+ * - React → Preact swap in production (smaller bundles)
8
+ * - Component aliasing: @yoamigo/core → @yoamigo/core/prod in production
9
+ * - Path aliases: @/ → src/
10
+ * - Environment variables: YA_* prefix
11
+ * - Build output configuration
12
+ *
13
+ * Usage:
14
+ * ```ts
15
+ * // vite.config.ts
16
+ * import { defineConfig } from 'vite'
17
+ * import { yoamigoPlugin } from '@yoamigo/core/plugin'
18
+ *
19
+ * export default defineConfig({
20
+ * plugins: [yoamigoPlugin()],
21
+ * })
22
+ * ```
23
+ */
24
+
25
+ interface YoamigoPluginOptions {
26
+ /**
27
+ * Additional Vite plugins to include
28
+ */
29
+ plugins?: UserConfig['plugins'];
30
+ /**
31
+ * Additional path aliases
32
+ */
33
+ aliases?: Record<string, string>;
34
+ /**
35
+ * Custom build options
36
+ */
37
+ build?: UserConfig['build'];
38
+ }
39
+ /**
40
+ * Creates the YoAmigo Vite plugin configuration.
41
+ *
42
+ * @param options - Optional customization options
43
+ * @returns Array of Vite plugins
44
+ */
45
+ declare function yoamigoPlugin(options?: YoamigoPluginOptions): Plugin[];
46
+
47
+ export { type YoamigoPluginOptions, yoamigoPlugin as default, yoamigoPlugin };
package/dist/plugin.js ADDED
@@ -0,0 +1,96 @@
1
+ // src/plugin/index.ts
2
+ import react from "@vitejs/plugin-react";
3
+ import preact from "@preact/preset-vite";
4
+ import path from "path";
5
+ function yoamigoPlugin(options = {}) {
6
+ const templateDir = process.cwd();
7
+ const resolveFromTemplate = (relativePath) => path.resolve(templateDir, relativePath);
8
+ return [
9
+ {
10
+ name: "yoamigo:config",
11
+ config(config, { mode }) {
12
+ const isProd = mode === "production";
13
+ const aliasArray = [
14
+ // Production aliases must come FIRST for priority
15
+ ...isProd ? [
16
+ // === React -> Preact (must be first for broad matching) ===
17
+ { find: "react", replacement: "preact/compat" },
18
+ { find: "react-dom/test-utils", replacement: "preact/test-utils" },
19
+ { find: "react-dom/client", replacement: "preact/compat/client" },
20
+ { find: "react-dom", replacement: "preact/compat" },
21
+ { find: "react/jsx-runtime", replacement: "preact/jsx-runtime" },
22
+ // === @yoamigo/core -> Production barrel ===
23
+ // Redirect the entire components import to use static versions.
24
+ // This removes Tiptap and editing UI from the production bundle.
25
+ {
26
+ find: /^@yoamigo\/core$/,
27
+ replacement: "@yoamigo/core/prod"
28
+ },
29
+ {
30
+ find: /^@yoamigo\/core\/lib$/,
31
+ replacement: "@yoamigo/core/lib/prod"
32
+ }
33
+ ] : [],
34
+ // === Template-specific path aliases ===
35
+ { find: "@", replacement: resolveFromTemplate("./src") },
36
+ { find: "@components", replacement: resolveFromTemplate("./src/components") },
37
+ { find: "@lib", replacement: resolveFromTemplate("./src/lib") },
38
+ { find: "@assets", replacement: resolveFromTemplate("./assets") },
39
+ // Add any custom aliases from options
40
+ ...Object.entries(options.aliases || {}).map(([find, replacement]) => ({
41
+ find,
42
+ replacement: resolveFromTemplate(replacement)
43
+ }))
44
+ ];
45
+ return {
46
+ plugins: [isProd ? preact() : react(), ...options.plugins || []],
47
+ // Expose YA_ prefixed env vars to client code
48
+ envPrefix: "YA_",
49
+ // Serve static files from public/ directory
50
+ publicDir: "public",
51
+ resolve: {
52
+ alias: aliasArray,
53
+ // Ensure single React instance across all packages (prevents "Invalid hook call" errors)
54
+ dedupe: ["react", "react-dom"]
55
+ },
56
+ server: {
57
+ port: 5173,
58
+ strictPort: false,
59
+ // Allow Vite to find next available port
60
+ hmr: {
61
+ // When behind a proxy (builder worker), HMR needs to connect through the proxy
62
+ // Setting these to undefined lets Vite auto-detect from the page URL
63
+ // This ensures HMR WebSocket connects to the proxy (router) not directly to Vite
64
+ clientPort: void 0,
65
+ host: void 0,
66
+ protocol: void 0
67
+ }
68
+ },
69
+ // Dynamic base URL for different deployment contexts:
70
+ // - Preview builds: /deploy-preview/{siteId}/ (passed via YA_BASE_URL env var)
71
+ // - Published builds: / (default, served from subdomain root)
72
+ // - Dev server: ignored (base only affects production builds)
73
+ base: process.env.YA_BASE_URL || "/",
74
+ build: {
75
+ outDir: "dist",
76
+ emptyOutDir: true,
77
+ rollupOptions: {
78
+ output: {
79
+ // Output to build/ to avoid confusion with public/assets/ (source images)
80
+ entryFileNames: "build/[name].[hash].js",
81
+ chunkFileNames: "build/[name].[hash].js",
82
+ assetFileNames: "build/[name].[hash].[ext]"
83
+ }
84
+ },
85
+ ...options.build
86
+ }
87
+ };
88
+ }
89
+ }
90
+ ];
91
+ }
92
+ var plugin_default = yoamigoPlugin;
93
+ export {
94
+ plugin_default as default,
95
+ yoamigoPlugin
96
+ };
package/dist/prod.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ export { a as ContentStore, E as ContentStoreMode, C as ContentStoreProvider, d as MarkdownText, e as MarkdownTextProps, P as PageInfo, b as StaticImage, c as StaticImageProps, M as StaticText, S as StaticTextProps, b as YaImage, c as YaImageProps, M as YaText, S as YaTextProps, u as useContentStore } from './MarkdownText-mylt-QX-.js';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+ import React from 'react';
4
+
5
+ interface StaticLinkProps {
6
+ fieldId: string;
7
+ href?: string;
8
+ className?: string;
9
+ as?: 'a' | 'span';
10
+ children?: React.ReactNode;
11
+ /** Optional click handler called after navigation */
12
+ onClick?: () => void;
13
+ }
14
+ declare function StaticLink({ fieldId, href: defaultHref, className, as: Component, children, onClick }: StaticLinkProps): react_jsx_runtime.JSX.Element;
15
+
16
+ /**
17
+ * SafeHtml (Production) - Renders trusted HTML without sanitization.
18
+ *
19
+ * Content is trusted because:
20
+ * 1. It's created in the builder using Tiptap (controlled markup)
21
+ * 2. Sanitized by DOMPurify when saved in the builder
22
+ * 3. Users can't inject arbitrary HTML into content.json
23
+ */
24
+ interface SafeHtmlProps {
25
+ content: string;
26
+ className?: string;
27
+ mode?: 'read-only' | 'inline-edit';
28
+ }
29
+ declare function SafeHtml({ content, className }: SafeHtmlProps): react_jsx_runtime.JSX.Element;
30
+
31
+ export { SafeHtml, type SafeHtmlProps, StaticLink, type StaticLinkProps, StaticLink as YaLink, type StaticLinkProps as YaLinkProps };
package/dist/prod.js ADDED
@@ -0,0 +1,295 @@
1
+ // src/components/ContentStoreProvider.prod.tsx
2
+ import { createContext, useContext } from "react";
3
+
4
+ // src/lib/content-registry.ts
5
+ var contentMap = /* @__PURE__ */ new Map();
6
+ function getContent(fieldId) {
7
+ return contentMap.get(fieldId) ?? "";
8
+ }
9
+ function getAllContent() {
10
+ return Object.fromEntries(contentMap);
11
+ }
12
+
13
+ // src/components/ContentStoreProvider.prod.tsx
14
+ import { jsx } from "react/jsx-runtime";
15
+ var contentMap2 = new Map(Object.entries(getAllContent()));
16
+ var staticStore = {
17
+ getValue: (fieldId) => contentMap2.get(fieldId) ?? "",
18
+ setValue: () => {
19
+ },
20
+ // No-op in production
21
+ mode: "read-only",
22
+ setMode: () => {
23
+ },
24
+ // No-op in production
25
+ subscribe: () => () => {
26
+ },
27
+ // No-op, return empty unsubscribe
28
+ saveToWorker: void 0
29
+ };
30
+ var ContentStoreContext = createContext(staticStore);
31
+ function useContentStore() {
32
+ return useContext(ContentStoreContext);
33
+ }
34
+ function ContentStoreProvider({ children }) {
35
+ return /* @__PURE__ */ jsx(ContentStoreContext.Provider, { value: staticStore, children });
36
+ }
37
+
38
+ // src/components/StaticText.tsx
39
+ import { jsx as jsx2 } from "react/jsx-runtime";
40
+ function MpText({ fieldId, className, as: Component = "span", children }) {
41
+ const content = getContent(fieldId) || (typeof children === "string" ? children : "");
42
+ return /* @__PURE__ */ jsx2(
43
+ Component,
44
+ {
45
+ className,
46
+ "data-field-id": fieldId,
47
+ dangerouslySetInnerHTML: { __html: content }
48
+ }
49
+ );
50
+ }
51
+
52
+ // src/lib/asset-resolver.ts
53
+ var assetResolver = (path) => path;
54
+ function resolveAssetUrl(path) {
55
+ if (!path) return "";
56
+ if (path.startsWith("http://") || path.startsWith("https://")) {
57
+ return path;
58
+ }
59
+ return assetResolver(path);
60
+ }
61
+
62
+ // src/components/StaticImage.tsx
63
+ import { jsx as jsx3 } from "react/jsx-runtime";
64
+ function parseImageValue(value) {
65
+ if (!value) {
66
+ return { src: "" };
67
+ }
68
+ try {
69
+ const parsed = JSON.parse(value);
70
+ if (typeof parsed === "object" && parsed.src) {
71
+ return parsed;
72
+ }
73
+ } catch {
74
+ }
75
+ return { src: value };
76
+ }
77
+ function getObjectPosition(imageData) {
78
+ if (imageData.focalPoint) {
79
+ return `${imageData.focalPoint.x}% ${imageData.focalPoint.y}%`;
80
+ }
81
+ return imageData.objectPosition || "50% 50%";
82
+ }
83
+ function MpImage({
84
+ fieldId,
85
+ className,
86
+ alt,
87
+ objectFit: propObjectFit,
88
+ objectPosition: propObjectPosition,
89
+ loading = "lazy",
90
+ fallbackSrc,
91
+ fallbackAlt
92
+ }) {
93
+ const rawValue = getContent(fieldId);
94
+ const imageData = parseImageValue(rawValue);
95
+ const src = imageData.src || fallbackSrc || "";
96
+ const altText = imageData.alt || alt || fallbackAlt || "";
97
+ const objectFit = imageData.objectFit || propObjectFit || "cover";
98
+ const objectPosition = getObjectPosition(imageData) || propObjectPosition || "50% 50%";
99
+ return /* @__PURE__ */ jsx3(
100
+ "img",
101
+ {
102
+ src: resolveAssetUrl(src),
103
+ alt: altText,
104
+ className,
105
+ style: {
106
+ objectFit,
107
+ objectPosition
108
+ },
109
+ loading,
110
+ "data-field-id": fieldId
111
+ }
112
+ );
113
+ }
114
+
115
+ // src/components/StaticLink.tsx
116
+ import { useLocation } from "wouter";
117
+
118
+ // src/components/SafeHtml.prod.tsx
119
+ import { jsx as jsx4 } from "react/jsx-runtime";
120
+ function SafeHtml({ content, className }) {
121
+ return /* @__PURE__ */ jsx4(
122
+ "span",
123
+ {
124
+ className,
125
+ dangerouslySetInnerHTML: { __html: content }
126
+ }
127
+ );
128
+ }
129
+
130
+ // src/components/StaticLink.tsx
131
+ import { jsx as jsx5 } from "react/jsx-runtime";
132
+ function isInternalPath(path) {
133
+ if (!path) return false;
134
+ if (path.startsWith("#")) return false;
135
+ if (path.startsWith("//")) return false;
136
+ if (path.includes("://")) return false;
137
+ if (path.startsWith("mailto:") || path.startsWith("tel:")) return false;
138
+ return path.startsWith("/");
139
+ }
140
+ function StaticLink({ fieldId, href: defaultHref = "#", className, as: Component = "a", children, onClick }) {
141
+ const { getValue, mode } = useContentStore();
142
+ const [, navigate] = useLocation();
143
+ const textFieldId = `${fieldId}.text`;
144
+ const hrefFieldId = `${fieldId}.href`;
145
+ const storeText = getValue(textFieldId);
146
+ const storeHref = getValue(hrefFieldId);
147
+ const href = storeHref || defaultHref;
148
+ const hasStoreText = Boolean(storeText);
149
+ const hasStringChildren = typeof children === "string";
150
+ const hasReactChildren = children && !hasStringChildren;
151
+ const handleClick = (e) => {
152
+ if (href.startsWith("#")) {
153
+ e.preventDefault();
154
+ const targetId = href.substring(1);
155
+ const targetElement = document.getElementById(targetId);
156
+ if (targetElement) {
157
+ const navHeight = 118;
158
+ const targetPosition = targetElement.offsetTop - navHeight;
159
+ window.scrollTo({
160
+ top: targetPosition,
161
+ behavior: "smooth"
162
+ });
163
+ }
164
+ onClick?.();
165
+ return;
166
+ }
167
+ if (isInternalPath(href)) {
168
+ e.preventDefault();
169
+ navigate(href);
170
+ onClick?.();
171
+ return;
172
+ }
173
+ onClick?.();
174
+ };
175
+ return /* @__PURE__ */ jsx5(
176
+ Component,
177
+ {
178
+ href: Component === "a" ? href : void 0,
179
+ onClick: handleClick,
180
+ className,
181
+ "data-ya-restricted": "true",
182
+ "data-field-id": fieldId,
183
+ children: hasStoreText || hasStringChildren ? /* @__PURE__ */ jsx5(SafeHtml, { content: storeText || children || "", mode }) : hasReactChildren ? children : null
184
+ }
185
+ );
186
+ }
187
+
188
+ // src/components/MarkdownText.tsx
189
+ import { Fragment } from "react";
190
+ import { jsx as jsx6 } from "react/jsx-runtime";
191
+ function tokenize(text) {
192
+ const tokens = [];
193
+ let remaining = text;
194
+ const patterns = [
195
+ // Bold: **text**
196
+ { regex: /^\*\*(.+?)\*\*/, type: "bold" },
197
+ // Italic: *text* (but not **)
198
+ { regex: /^\*([^*]+?)\*/, type: "italic" },
199
+ // Link: [text](url)
200
+ { regex: /^\[([^\]]+)\]\(([^)]+)\)/, type: "link" },
201
+ // Newline
202
+ { regex: /^\n/, type: "newline" }
203
+ ];
204
+ while (remaining.length > 0) {
205
+ let matched = false;
206
+ for (const pattern of patterns) {
207
+ const match = remaining.match(pattern.regex);
208
+ if (match) {
209
+ if (pattern.type === "bold") {
210
+ tokens.push({ type: "bold", content: match[1] });
211
+ } else if (pattern.type === "italic") {
212
+ tokens.push({ type: "italic", content: match[1] });
213
+ } else if (pattern.type === "link") {
214
+ tokens.push({ type: "link", text: match[1], url: match[2] });
215
+ } else if (pattern.type === "newline") {
216
+ tokens.push({ type: "newline" });
217
+ }
218
+ remaining = remaining.slice(match[0].length);
219
+ matched = true;
220
+ break;
221
+ }
222
+ }
223
+ if (!matched) {
224
+ const nextSpecial = remaining.search(/[*[\n]/);
225
+ if (nextSpecial === -1) {
226
+ tokens.push({ type: "text", content: remaining });
227
+ remaining = "";
228
+ } else if (nextSpecial === 0) {
229
+ tokens.push({ type: "text", content: remaining[0] });
230
+ remaining = remaining.slice(1);
231
+ } else {
232
+ tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
233
+ remaining = remaining.slice(nextSpecial);
234
+ }
235
+ }
236
+ }
237
+ const merged = [];
238
+ for (const token of tokens) {
239
+ const last = merged[merged.length - 1];
240
+ if (token.type === "text" && last?.type === "text") {
241
+ last.content += token.content;
242
+ } else {
243
+ merged.push(token);
244
+ }
245
+ }
246
+ return merged;
247
+ }
248
+ function tokensToElements(tokens) {
249
+ return tokens.map((token, index) => {
250
+ switch (token.type) {
251
+ case "text":
252
+ return /* @__PURE__ */ jsx6(Fragment, { children: token.content }, index);
253
+ case "bold":
254
+ return /* @__PURE__ */ jsx6("strong", { children: token.content }, index);
255
+ case "italic":
256
+ return /* @__PURE__ */ jsx6("em", { children: token.content }, index);
257
+ case "link":
258
+ return /* @__PURE__ */ jsx6(
259
+ "a",
260
+ {
261
+ href: token.url,
262
+ target: "_blank",
263
+ rel: "noopener noreferrer",
264
+ className: "text-[var(--color-primary)] underline hover:text-[var(--color-secondary)]",
265
+ children: token.text
266
+ },
267
+ index
268
+ );
269
+ case "newline":
270
+ return /* @__PURE__ */ jsx6("br", {}, index);
271
+ default:
272
+ return null;
273
+ }
274
+ });
275
+ }
276
+ function parseMarkdownToElements(content) {
277
+ const tokens = tokenize(content);
278
+ return tokensToElements(tokens);
279
+ }
280
+ function MarkdownText({ content, className }) {
281
+ const elements = parseMarkdownToElements(content);
282
+ return /* @__PURE__ */ jsx6("span", { className, children: elements });
283
+ }
284
+ export {
285
+ ContentStoreProvider,
286
+ MarkdownText,
287
+ SafeHtml,
288
+ MpImage as StaticImage,
289
+ StaticLink,
290
+ MpText as StaticText,
291
+ MpImage as YaImage,
292
+ StaticLink as YaLink,
293
+ MpText as YaText,
294
+ useContentStore
295
+ };
@@ -0,0 +1,46 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, MouseEvent } from 'react';
3
+
4
+ /**
5
+ * Router Abstraction - Shared Types
6
+ *
7
+ * These types are used by both development (React Router) and
8
+ * production (wouter) router implementations.
9
+ */
10
+
11
+ interface LinkProps {
12
+ /** Target path (alias: href) */
13
+ to?: string;
14
+ /** Target path (alias: to) */
15
+ href?: string;
16
+ children: ReactNode;
17
+ className?: string;
18
+ onClick?: (e: MouseEvent<HTMLAnchorElement>) => void;
19
+ replace?: boolean;
20
+ [key: string]: unknown;
21
+ }
22
+ interface RouterProps$1 {
23
+ children: ReactNode;
24
+ base?: string;
25
+ }
26
+ type NavigateFunction = (to: string, options?: {
27
+ replace?: boolean;
28
+ }) => void;
29
+
30
+ declare function Link({ to, href, children, className, onClick, replace, ...props }: LinkProps): react_jsx_runtime.JSX.Element;
31
+
32
+ /**
33
+ * useNavigate Hook - Production (wouter)
34
+ *
35
+ * Provides React Router-like useNavigate API using wouter's useLocation.
36
+ */
37
+
38
+ declare function useNavigate(): NavigateFunction;
39
+
40
+ interface RouterProps {
41
+ children: ReactNode;
42
+ base?: string;
43
+ }
44
+ declare function Router({ children, base }: RouterProps): react_jsx_runtime.JSX.Element;
45
+
46
+ export { Link, type LinkProps, type NavigateFunction, Router, type RouterProps$1 as RouterProps, useNavigate };
package/dist/router.js ADDED
@@ -0,0 +1,42 @@
1
+ // src/router/Link.tsx
2
+ import { Link as WouterLink } from "wouter";
3
+ import { jsx } from "react/jsx-runtime";
4
+ function Link({ to, href, children, className, onClick, replace, ...props }) {
5
+ const target = href ?? to ?? "/";
6
+ return /* @__PURE__ */ jsx(WouterLink, { href: target, className, onClick, replace, ...props, children });
7
+ }
8
+
9
+ // src/router/useNavigate.ts
10
+ import { useLocation } from "wouter";
11
+ function useNavigate() {
12
+ const [, setLocation] = useLocation();
13
+ return (to, options) => {
14
+ if (options?.replace) {
15
+ window.history.replaceState(null, "", to);
16
+ setLocation(to);
17
+ } else {
18
+ setLocation(to);
19
+ }
20
+ };
21
+ }
22
+
23
+ // src/router/Router.tsx
24
+ import { Router as WouterRouter } from "wouter";
25
+ import { jsx as jsx2 } from "react/jsx-runtime";
26
+ function detectBasename() {
27
+ if (typeof window === "undefined") return "";
28
+ const sessionMatch = window.location.pathname.match(/^\/session\/[^/]+/);
29
+ if (sessionMatch) return sessionMatch[0];
30
+ const previewMatch = window.location.pathname.match(/^\/deploy-preview\/[^/]+/);
31
+ if (previewMatch) return previewMatch[0];
32
+ return "";
33
+ }
34
+ function Router({ children, base }) {
35
+ const basename = base ?? detectBasename();
36
+ return /* @__PURE__ */ jsx2(WouterRouter, { base: basename, children });
37
+ }
38
+ export {
39
+ Link,
40
+ Router,
41
+ useNavigate
42
+ };
package/package.json ADDED
@@ -0,0 +1,115 @@
1
+ {
2
+ "name": "@yoamigo.com/core",
3
+ "version": "0.1.0",
4
+ "description": "Core components, router, and utilities for YoAmigo templates",
5
+ "type": "module",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./plugin": {
15
+ "types": "./dist/plugin.d.ts",
16
+ "import": "./dist/plugin.js"
17
+ },
18
+ "./prod": {
19
+ "types": "./dist/prod.d.ts",
20
+ "import": "./dist/prod.js"
21
+ },
22
+ "./router": {
23
+ "types": "./dist/router.d.ts",
24
+ "import": "./dist/router.js"
25
+ },
26
+ "./lib": {
27
+ "types": "./dist/lib.d.ts",
28
+ "import": "./dist/lib.js"
29
+ },
30
+ "./lib/prod": {
31
+ "types": "./dist/lib-prod.d.ts",
32
+ "import": "./dist/lib-prod.js"
33
+ },
34
+ "./styles": "./src/styles/index.css",
35
+ "./styles/*": "./src/styles/*"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "src/styles",
40
+ "LICENSE",
41
+ "README.md"
42
+ ],
43
+ "sideEffects": [
44
+ "*.css"
45
+ ],
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/yoamigo/sdk.git",
52
+ "directory": "packages/yoamigo-core"
53
+ },
54
+ "homepage": "https://yoamigo.com/developers",
55
+ "bugs": {
56
+ "url": "https://github.com/yoamigo/sdk/issues"
57
+ },
58
+ "keywords": [
59
+ "yoamigo",
60
+ "vite",
61
+ "vite-plugin",
62
+ "template",
63
+ "react",
64
+ "preact",
65
+ "website-builder"
66
+ ],
67
+ "scripts": {
68
+ "build": "tsup",
69
+ "dev": "tsup --watch",
70
+ "typecheck": "tsc --noEmit",
71
+ "lint": "eslint src --ext .ts,.tsx",
72
+ "lint:check": "eslint src --ext .ts,.tsx"
73
+ },
74
+ "dependencies": {
75
+ "clsx": "^2.1.1",
76
+ "preact": "^10.27.2",
77
+ "wouter": "^3.8.0"
78
+ },
79
+ "devDependencies": {
80
+ "@preact/preset-vite": "^2.8.0",
81
+ "@tiptap/core": "^3.11.1",
82
+ "@tiptap/extension-link": "^3.11.1",
83
+ "@tiptap/extension-text-style": "^3.11.1",
84
+ "@tiptap/pm": "^3.11.1",
85
+ "@tiptap/react": "^3.11.1",
86
+ "@tiptap/starter-kit": "^3.11.1",
87
+ "@types/dompurify": "^3.0.5",
88
+ "@types/node": "^20.0.0",
89
+ "@types/react": "^19.2.1",
90
+ "@types/react-dom": "^19.2.1",
91
+ "@vitejs/plugin-react": "^5.1.0",
92
+ "dompurify": "^3.2.3",
93
+ "react": "^19.2.1",
94
+ "react-dom": "^19.2.1",
95
+ "tsup": "^8.5.0",
96
+ "typescript": "^5.9.3",
97
+ "vite": "^7.2.4"
98
+ },
99
+ "peerDependencies": {
100
+ "react": "^18.0.0 || ^19.0.0",
101
+ "react-dom": "^18.0.0 || ^19.0.0",
102
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0"
103
+ },
104
+ "peerDependenciesMeta": {
105
+ "react": {
106
+ "optional": true
107
+ },
108
+ "react-dom": {
109
+ "optional": true
110
+ },
111
+ "vite": {
112
+ "optional": true
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,5 @@
1
+ /* @yoamigo/core styles - import all component styles */
2
+ @import '../components/ya-text.css';
3
+ @import '../components/ya-image.css';
4
+ @import '../components/ya-link.css';
5
+ @import '../components/ya-tooltip.css';