yaxa-svelte 1.3.0 → 1.5.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.
Files changed (64) hide show
  1. package/README.md +18 -12
  2. package/dist/actions/autosize.d.ts +16 -0
  3. package/dist/actions/autosize.js +38 -0
  4. package/dist/actions/clickOutside.d.ts +18 -0
  5. package/dist/actions/clickOutside.js +46 -0
  6. package/dist/actions/index.d.ts +10 -0
  7. package/dist/actions/index.js +5 -0
  8. package/dist/actions/infiniteScroll.d.ts +21 -0
  9. package/dist/actions/infiniteScroll.js +62 -0
  10. package/dist/actions/portal.d.ts +17 -0
  11. package/dist/actions/portal.js +63 -0
  12. package/dist/actions/sortable.d.ts +18 -0
  13. package/dist/actions/sortable.js +66 -0
  14. package/dist/components/elements/CodeBlock.svelte +373 -0
  15. package/dist/components/elements/CodeBlock.svelte.d.ts +17 -0
  16. package/dist/components/elements/DataTable.svelte +115 -23
  17. package/dist/components/elements/DataTable.svelte.d.ts +5 -0
  18. package/dist/components/elements/Icon.svelte +41 -1
  19. package/dist/components/elements/MetricCard.svelte +228 -0
  20. package/dist/components/elements/MetricCard.svelte.d.ts +19 -0
  21. package/dist/components/elements/Skeleton.svelte +59 -8
  22. package/dist/components/elements/Skeleton.svelte.d.ts +44 -3
  23. package/dist/components/elements/SortableList.svelte +150 -0
  24. package/dist/components/elements/SortableList.svelte.d.ts +39 -0
  25. package/dist/components/forms/DatePicker.svelte +322 -0
  26. package/dist/components/forms/DatePicker.svelte.d.ts +17 -0
  27. package/dist/components/forms/DateRangePicker.svelte +397 -0
  28. package/dist/components/forms/DateRangePicker.svelte.d.ts +27 -0
  29. package/dist/components/forms/Dropzone.svelte +251 -0
  30. package/dist/components/forms/Dropzone.svelte.d.ts +21 -0
  31. package/dist/components/forms/InputOTP.svelte +165 -0
  32. package/dist/components/forms/InputOTP.svelte.d.ts +17 -0
  33. package/dist/components/forms/Textarea.svelte +32 -6
  34. package/dist/components/forms/Textarea.svelte.d.ts +2 -0
  35. package/dist/components/forms/ToggleGroup.svelte +151 -0
  36. package/dist/components/forms/ToggleGroup.svelte.d.ts +22 -0
  37. package/dist/components/layout/Footer.svelte +33 -7
  38. package/dist/components/layout/Footer.svelte.d.ts +1 -1
  39. package/dist/components/seo/Favicons.svelte +30 -2
  40. package/dist/components/seo/Favicons.svelte.d.ts +2 -0
  41. package/dist/components/seo/Seo.svelte +28 -4
  42. package/dist/components/seo/Seo.svelte.d.ts +1 -1
  43. package/dist/composables/useFormAction.svelte.d.ts +45 -0
  44. package/dist/composables/useFormAction.svelte.js +75 -0
  45. package/dist/composables/useInfiniteScroll.svelte.d.ts +29 -0
  46. package/dist/composables/useInfiniteScroll.svelte.js +61 -0
  47. package/dist/composables/useLocale.svelte.d.ts +55 -0
  48. package/dist/composables/useLocale.svelte.js +205 -0
  49. package/dist/composables/useSortable.svelte.d.ts +27 -0
  50. package/dist/composables/useSortable.svelte.js +83 -0
  51. package/dist/index.d.ts +31 -5
  52. package/dist/index.js +17 -3
  53. package/dist/site/config.d.ts +27 -1
  54. package/dist/site/config.js +60 -15
  55. package/dist/site/og.d.ts +2 -1
  56. package/dist/site/og.js +41 -25
  57. package/dist/site/robots.d.ts +4 -0
  58. package/dist/site/robots.js +24 -6
  59. package/dist/site/schema.d.ts +49 -1
  60. package/dist/site/schema.js +73 -2
  61. package/dist/site/sitemap.d.ts +7 -1
  62. package/dist/site/sitemap.js +65 -26
  63. package/dist/styles/yaxa.css +70 -0
  64. package/package.json +1 -1
package/README.md CHANGED
@@ -68,7 +68,7 @@ export default defineConfig({
68
68
 
69
69
  ### 3. Define Your Site Configuration
70
70
 
71
- Create `src/site.config.ts` — your single source of truth for branding, metadata, and SEO:
71
+ Create `src/site.config.ts` — your single source of truth for branding, metadata, licensing, and SEO:
72
72
 
73
73
  ```ts
74
74
  // src/site.config.ts
@@ -79,14 +79,20 @@ export const siteConfig = defineSiteConfig({
79
79
  title: 'My Indie SaaS — Build Fast with SvelteKit',
80
80
  description: 'Fast, beautiful, accessible web applications.',
81
81
  url: 'https://my-app.com',
82
+ // Single-email mode: Solo devs can set one email for contact, support & DPO
83
+ email: 'hello@my-app.com',
84
+ project: {
85
+ license: 'MIT',
86
+ type: 'open-source',
87
+ repositoryUrl: 'https://github.com/my-org/my-app'
88
+ },
82
89
  theme: {
83
90
  accent: 'svelte', // 'svelte' | 'emerald' | 'amber' | 'sky' | 'violet' | 'rose' | 'indigo'
84
91
  neutral: 'zinc', // 'zinc' | 'slate' | 'stone' | 'neutral'
85
92
  defaultMode: 'dark'
86
93
  },
87
94
  socials: {
88
- github: 'https://github.com/my-org/my-app',
89
- twitter: '@my_app'
95
+ github: 'https://github.com/my-org/my-app'
90
96
  }
91
97
  });
92
98
  ```
@@ -219,15 +225,15 @@ export const POST = createPolarWebhookHandler();
219
225
 
220
226
  ## 🧩 Component Library
221
227
 
222
- | Category | Components |
223
- | :----------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
224
- | **SaaS Suite** | `<Gate>`, `<AuthCard>`, `<UserMenu>`, `<PricingCard>`, `<PricingTable>`, `<SubscriptionCard>`, `useAuth`, `useGate`, `useUpload` |
225
- | **Admin Suite** | `<AdminDashboard>`, `<RecordDrawer>`, `<DevSandbox>`, `<ImpersonationBanner>`, `createYaxaAdminHook`, `createDrizzleAdmin` |
226
- | **Elements** | `Button`, `ButtonGroup`, `Badge`, `Avatar`, `AvatarGroup`, `DataTable`, `Chip`, `Meter`, `Kbd`, `Icon`, `Spinner`, `Progress`, `Skeleton`, `Link`, `Logo` |
227
- | **Forms** | `Form`, `FormField`, `Input`, `Textarea`, `Checkbox`, `Switch`, `Select`, `RadioGroup`, `Slider`, `ColorPicker` |
228
- | **Layout** | `Container`, `Header`, `Footer`, `Section`, `Card`, `Divider`, `YaxaApp` |
229
- | **Overlays & Nav** | `Tabs`, `Breadcrumb`, `Pagination`, `CommandPalette` (`⌘K`), `DropdownMenu`, `ContextMenu`, `Modal`, `Slideover`, `Popover`, `Tooltip`, `Alert`, `Accordion` |
230
- | **Composables** | `useAuth`, `useGate`, `useUpload`, `useClipboard`, `useShortcuts`, `useColorMode`, `useToast`, `useMediaQuery`, `useDebounce` |
228
+ | Category | Components |
229
+ | :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
230
+ | **SaaS Suite** | `<Gate>`, `<AuthCard>`, `<UserMenu>`, `<PricingCard>`, `<PricingTable>`, `<SubscriptionCard>`, `useAuth`, `useGate`, `useUpload` |
231
+ | **Admin Suite** | `<AdminDashboard>`, `<RecordDrawer>`, `<DevSandbox>`, `<ImpersonationBanner>`, `createYaxaAdminHook`, `createDrizzleAdmin` |
232
+ | **Elements** | `Button`, `ButtonGroup`, `Badge`, `Avatar`, `AvatarGroup`, `DataTable`, `Chip`, `Meter`, `MetricCard`, `Kbd`, `Icon`, `Spinner`, `Progress`, `Skeleton`, `Link`, `Logo` |
233
+ | **Forms** | `Form`, `FormField`, `Input`, `InputOTP`, `Textarea`, `Checkbox`, `Switch`, `Select`, `RadioGroup`, `Slider`, `ColorPicker`, `ToggleGroup`, `DatePicker`, `DateRangePicker` |
234
+ | **Layout & Blocks** | `Container`, `Header`, `Footer`, `Section`, `Card`, `Divider`, `YaxaApp`, Page Blocks (Hero, SaaS Metrics, 2FA Security) |
235
+ | **Overlays & Nav** | `Tabs`, `Breadcrumb`, `Pagination`, `CommandPalette` (`⌘K`), `DropdownMenu`, `ContextMenu`, `Modal`, `Slideover`, `Popover`, `Tooltip`, `Alert`, `Accordion` |
236
+ | **Composables** | `useAuth`, `useGate`, `useUpload`, `useClipboard`, `useShortcuts`, `useColorMode`, `useToast`, `useMediaQuery`, `useDebounce` |
231
237
 
232
238
  ---
233
239
 
@@ -0,0 +1,16 @@
1
+ import type { Action } from 'svelte/action';
2
+ export interface AutosizeOptions {
3
+ /** Maximum height in pixels before scrolling */
4
+ maxHeight?: number;
5
+ /** Minimum height in pixels (defaults to initial height) */
6
+ minHeight?: number;
7
+ }
8
+ /**
9
+ * Headless Svelte Action to dynamically auto-grow a <textarea> based on its content.
10
+ *
11
+ * Usage:
12
+ * ```svelte
13
+ * <textarea use:autosize={{ maxHeight: 300 }} bind:value={text}></textarea>
14
+ * ```
15
+ */
16
+ export declare const autosize: Action<HTMLTextAreaElement, AutosizeOptions | undefined>;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Headless Svelte Action to dynamically auto-grow a <textarea> based on its content.
3
+ *
4
+ * Usage:
5
+ * ```svelte
6
+ * <textarea use:autosize={{ maxHeight: 300 }} bind:value={text}></textarea>
7
+ * ```
8
+ */
9
+ export const autosize = (node, options = {}) => {
10
+ let currentOptions = options || {};
11
+ function resize() {
12
+ // Reset height to calculate true scrollHeight
13
+ node.style.height = 'auto';
14
+ const minH = currentOptions.minHeight ?? 0;
15
+ const maxH = currentOptions.maxHeight;
16
+ let targetHeight = Math.max(node.scrollHeight, minH);
17
+ if (maxH && targetHeight > maxH) {
18
+ targetHeight = maxH;
19
+ node.style.overflowY = 'auto';
20
+ }
21
+ else {
22
+ node.style.overflowY = 'hidden';
23
+ }
24
+ node.style.height = `${targetHeight}px`;
25
+ }
26
+ node.addEventListener('input', resize);
27
+ // Initial resize
28
+ requestAnimationFrame(resize);
29
+ return {
30
+ update(newOptions) {
31
+ currentOptions = newOptions || {};
32
+ resize();
33
+ },
34
+ destroy() {
35
+ node.removeEventListener('input', resize);
36
+ }
37
+ };
38
+ };
@@ -0,0 +1,18 @@
1
+ import type { Action } from 'svelte/action';
2
+ export interface ClickOutsideOptions {
3
+ /** Callback invoked when a click occurs outside the node */
4
+ handler?: (event: MouseEvent | TouchEvent) => void;
5
+ /** Optional list of elements or selectors to ignore */
6
+ exclude?: (HTMLElement | string)[];
7
+ /** Enabled flag */
8
+ enabled?: boolean;
9
+ }
10
+ /**
11
+ * Headless Svelte Action to trigger a callback when clicking outside the target element.
12
+ *
13
+ * Usage:
14
+ * ```svelte
15
+ * <div use:clickOutside={() => (isOpen = false)}>...</div>
16
+ * ```
17
+ */
18
+ export declare const clickOutside: Action<HTMLElement, ClickOutsideOptions | ((event: MouseEvent | TouchEvent) => void) | undefined>;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Headless Svelte Action to trigger a callback when clicking outside the target element.
3
+ *
4
+ * Usage:
5
+ * ```svelte
6
+ * <div use:clickOutside={() => (isOpen = false)}>...</div>
7
+ * ```
8
+ */
9
+ export const clickOutside = (node, param) => {
10
+ let options = typeof param === 'function' ? { handler: param } : param || {};
11
+ function handleClick(event) {
12
+ if (options.enabled === false)
13
+ return;
14
+ const target = event.target;
15
+ if (!target)
16
+ return;
17
+ // Check if click was inside node
18
+ if (node.contains(target))
19
+ return;
20
+ // Check excluded elements
21
+ if (options.exclude) {
22
+ for (const item of options.exclude) {
23
+ if (typeof item === 'string') {
24
+ const el = document.querySelector(item);
25
+ if (el && el.contains(target))
26
+ return;
27
+ }
28
+ else if (item && item.contains(target)) {
29
+ return;
30
+ }
31
+ }
32
+ }
33
+ if (options.handler) {
34
+ options.handler(event);
35
+ }
36
+ }
37
+ document.addEventListener('pointerdown', handleClick, true);
38
+ return {
39
+ update(newParam) {
40
+ options = typeof newParam === 'function' ? { handler: newParam } : newParam || {};
41
+ },
42
+ destroy() {
43
+ document.removeEventListener('pointerdown', handleClick, true);
44
+ }
45
+ };
46
+ };
@@ -0,0 +1,10 @@
1
+ export { autosize } from './autosize';
2
+ export type { AutosizeOptions } from './autosize';
3
+ export { clickOutside } from './clickOutside';
4
+ export type { ClickOutsideOptions } from './clickOutside';
5
+ export { portal } from './portal';
6
+ export type { PortalOptions } from './portal';
7
+ export { infiniteScroll } from './infiniteScroll';
8
+ export type { InfiniteScrollActionOptions } from './infiniteScroll';
9
+ export { sortableItem } from './sortable';
10
+ export type { SortableItemOptions } from './sortable';
@@ -0,0 +1,5 @@
1
+ export { autosize } from './autosize';
2
+ export { clickOutside } from './clickOutside';
3
+ export { portal } from './portal';
4
+ export { infiniteScroll } from './infiniteScroll';
5
+ export { sortableItem } from './sortable';
@@ -0,0 +1,21 @@
1
+ import type { Action } from 'svelte/action';
2
+ export interface InfiniteScrollActionOptions {
3
+ /** Threshold in pixels from bottom/top to trigger (default: 100) */
4
+ distance?: number;
5
+ /** Direction to monitor (default: 'bottom') */
6
+ direction?: 'bottom' | 'top';
7
+ /** Disable infinite scroll triggering */
8
+ disabled?: boolean;
9
+ /** Callback invoked when trigger threshold is reached */
10
+ onLoadMore: () => Promise<void> | void;
11
+ }
12
+ /**
13
+ * Headless Svelte Action to trigger loading callbacks when scrolling near the edges.
14
+ *
15
+ * Usage:
16
+ * ```svelte
17
+ * <div use:infiniteScroll={loadMore}>...</div>
18
+ * <div use:infiniteScroll={{ onLoadMore: loadMore, distance: 200 }}>...</div>
19
+ * ```
20
+ */
21
+ export declare const infiniteScroll: Action<HTMLElement, InfiniteScrollActionOptions | (() => Promise<void> | void)>;
@@ -0,0 +1,62 @@
1
+ import { browser } from '$app/environment';
2
+ /**
3
+ * Headless Svelte Action to trigger loading callbacks when scrolling near the edges.
4
+ *
5
+ * Usage:
6
+ * ```svelte
7
+ * <div use:infiniteScroll={loadMore}>...</div>
8
+ * <div use:infiniteScroll={{ onLoadMore: loadMore, distance: 200 }}>...</div>
9
+ * ```
10
+ */
11
+ export const infiniteScroll = (node, param) => {
12
+ if (!browser)
13
+ return;
14
+ let options = typeof param === 'function' ? { onLoadMore: param } : param;
15
+ let isPending = false;
16
+ async function trigger() {
17
+ if (isPending || options.disabled)
18
+ return;
19
+ try {
20
+ isPending = true;
21
+ await options.onLoadMore();
22
+ }
23
+ finally {
24
+ isPending = false;
25
+ }
26
+ }
27
+ const distance = options.distance ?? 100;
28
+ const direction = options.direction ?? 'bottom';
29
+ const sentinel = document.createElement('div');
30
+ sentinel.setAttribute('data-yaxa-sentinel', 'true');
31
+ sentinel.style.height = '1px';
32
+ sentinel.style.width = '100%';
33
+ sentinel.style.pointerEvents = 'none';
34
+ sentinel.style.opacity = '0';
35
+ if (direction === 'bottom') {
36
+ node.appendChild(sentinel);
37
+ }
38
+ else {
39
+ node.insertBefore(sentinel, node.firstChild);
40
+ }
41
+ const observer = new IntersectionObserver((entries) => {
42
+ const [entry] = entries;
43
+ if (entry.isIntersecting && !isPending && !options.disabled) {
44
+ trigger();
45
+ }
46
+ }, {
47
+ root: node === document.documentElement || node === document.body ? null : node,
48
+ rootMargin: `${distance}px`
49
+ });
50
+ observer.observe(sentinel);
51
+ return {
52
+ update(newParam) {
53
+ options = typeof newParam === 'function' ? { onLoadMore: newParam } : newParam;
54
+ },
55
+ destroy() {
56
+ observer.disconnect();
57
+ if (sentinel.parentNode) {
58
+ sentinel.parentNode.removeChild(sentinel);
59
+ }
60
+ }
61
+ };
62
+ };
@@ -0,0 +1,17 @@
1
+ import type { Action } from 'svelte/action';
2
+ export interface PortalOptions {
3
+ /** Target container element or CSS selector. Defaults to `document.body` */
4
+ target?: HTMLElement | string;
5
+ /** Whether the portal is enabled */
6
+ enabled?: boolean;
7
+ }
8
+ /**
9
+ * Headless Svelte Action to teleport an element into another DOM container (e.g. `document.body`).
10
+ *
11
+ * Usage:
12
+ * ```svelte
13
+ * <div use:portal>...</div>
14
+ * <div use:portal="#modal-root">...</div>
15
+ * ```
16
+ */
17
+ export declare const portal: Action<HTMLElement, HTMLElement | string | PortalOptions | undefined>;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Headless Svelte Action to teleport an element into another DOM container (e.g. `document.body`).
3
+ *
4
+ * Usage:
5
+ * ```svelte
6
+ * <div use:portal>...</div>
7
+ * <div use:portal="#modal-root">...</div>
8
+ * ```
9
+ */
10
+ export const portal = (node, param) => {
11
+ let targetEl = null;
12
+ const placeholder = document.createComment('portal-placeholder');
13
+ function resolveTarget(p) {
14
+ if (!p)
15
+ return document.body;
16
+ if (typeof p === 'string')
17
+ return document.querySelector(p);
18
+ if (p instanceof HTMLElement)
19
+ return p;
20
+ if (typeof p === 'object') {
21
+ if (p.enabled === false)
22
+ return null;
23
+ if (typeof p.target === 'string')
24
+ return document.querySelector(p.target);
25
+ if (p.target instanceof HTMLElement)
26
+ return p.target;
27
+ return document.body;
28
+ }
29
+ return document.body;
30
+ }
31
+ function mount(target) {
32
+ if (!target) {
33
+ // Restore to placeholder if disabled
34
+ if (placeholder.parentNode && node.parentNode !== placeholder.parentNode) {
35
+ placeholder.parentNode.insertBefore(node, placeholder);
36
+ }
37
+ return;
38
+ }
39
+ if (node.parentNode && node.parentNode !== target) {
40
+ node.parentNode.insertBefore(placeholder, node);
41
+ target.appendChild(node);
42
+ }
43
+ else if (!node.parentNode) {
44
+ target.appendChild(node);
45
+ }
46
+ }
47
+ targetEl = resolveTarget(param);
48
+ mount(targetEl);
49
+ return {
50
+ update(newParam) {
51
+ targetEl = resolveTarget(newParam);
52
+ mount(targetEl);
53
+ },
54
+ destroy() {
55
+ if (placeholder.parentNode) {
56
+ placeholder.parentNode.removeChild(placeholder);
57
+ }
58
+ if (node.parentNode) {
59
+ node.parentNode.removeChild(node);
60
+ }
61
+ }
62
+ };
63
+ };
@@ -0,0 +1,18 @@
1
+ import type { Action } from 'svelte/action';
2
+ export interface SortableItemOptions {
3
+ index: number;
4
+ disabled?: boolean;
5
+ onDragStart?: (index: number, e: DragEvent) => void;
6
+ onDragOver?: (index: number, e: DragEvent) => void;
7
+ onDrop?: (index: number, e: DragEvent) => void;
8
+ onDragEnd?: () => void;
9
+ }
10
+ /**
11
+ * Headless Svelte Action to make any DOM item draggable and droppable for reordering.
12
+ *
13
+ * Usage:
14
+ * ```svelte
15
+ * <li use:sortableItem={{ index, onDragStart, onDragOver, onDrop, onDragEnd }}>...</li>
16
+ * ```
17
+ */
18
+ export declare const sortableItem: Action<HTMLElement, SortableItemOptions>;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Headless Svelte Action to make any DOM item draggable and droppable for reordering.
3
+ *
4
+ * Usage:
5
+ * ```svelte
6
+ * <li use:sortableItem={{ index, onDragStart, onDragOver, onDrop, onDragEnd }}>...</li>
7
+ * ```
8
+ */
9
+ export const sortableItem = (node, options) => {
10
+ let currentOptions = options;
11
+ function setupDraggable() {
12
+ node.draggable = !currentOptions.disabled;
13
+ }
14
+ function handleDragStart(e) {
15
+ if (currentOptions.disabled)
16
+ return;
17
+ if (e.dataTransfer) {
18
+ e.dataTransfer.effectAllowed = 'move';
19
+ e.dataTransfer.setData('text/plain', String(currentOptions.index));
20
+ }
21
+ if (currentOptions.onDragStart) {
22
+ currentOptions.onDragStart(currentOptions.index, e);
23
+ }
24
+ }
25
+ function handleDragOver(e) {
26
+ if (currentOptions.disabled)
27
+ return;
28
+ e.preventDefault();
29
+ if (e.dataTransfer) {
30
+ e.dataTransfer.dropEffect = 'move';
31
+ }
32
+ if (currentOptions.onDragOver) {
33
+ currentOptions.onDragOver(currentOptions.index, e);
34
+ }
35
+ }
36
+ function handleDrop(e) {
37
+ if (currentOptions.disabled)
38
+ return;
39
+ e.preventDefault();
40
+ if (currentOptions.onDrop) {
41
+ currentOptions.onDrop(currentOptions.index, e);
42
+ }
43
+ }
44
+ function handleDragEnd() {
45
+ if (currentOptions.onDragEnd) {
46
+ currentOptions.onDragEnd();
47
+ }
48
+ }
49
+ setupDraggable();
50
+ node.addEventListener('dragstart', handleDragStart);
51
+ node.addEventListener('dragover', handleDragOver);
52
+ node.addEventListener('drop', handleDrop);
53
+ node.addEventListener('dragend', handleDragEnd);
54
+ return {
55
+ update(newOptions) {
56
+ currentOptions = newOptions;
57
+ setupDraggable();
58
+ },
59
+ destroy() {
60
+ node.removeEventListener('dragstart', handleDragStart);
61
+ node.removeEventListener('dragover', handleDragOver);
62
+ node.removeEventListener('drop', handleDrop);
63
+ node.removeEventListener('dragend', handleDragEnd);
64
+ }
65
+ };
66
+ };