@warkypublic/svelix 0.1.26 → 0.1.27

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 (37) hide show
  1. package/dist/components/BetterMenu/MenuRenderer.svelte +8 -7
  2. package/dist/components/Boxer/Boxer.svelte +2 -4
  3. package/dist/components/ContentEditor/ContentEditor.svelte +7 -1
  4. package/dist/components/ContentEditor/subcomponents/AudioPlayer.svelte +0 -1
  5. package/dist/components/ContentEditor/subcomponents/CollaboraEditor.svelte +1 -1
  6. package/dist/components/ContentEditor/subcomponents/EmailViewer.svelte +1 -1
  7. package/dist/components/ContentEditor/subcomponents/MarkdownViewer.svelte +33 -8
  8. package/dist/components/ContentEditor/subcomponents/MonacoEditor.svelte +10 -20
  9. package/dist/components/ContentEditor/subcomponents/Office365Editor.svelte +7 -3
  10. package/dist/components/ContentEditor/subcomponents/PdfViewer.svelte +4 -5
  11. package/dist/components/ContentEditor/subcomponents/TextEditor.svelte +194 -185
  12. package/dist/components/ContentEditor/subcomponents/VideoPlayer.svelte +0 -1
  13. package/dist/components/ContentEditor/subcomponents/ZipViewer.svelte +1 -1
  14. package/dist/components/ContentEditor/types.d.ts +7 -0
  15. package/dist/components/ContentEditor/utils.d.ts +2 -0
  16. package/dist/components/ContentEditor/utils.js +71 -0
  17. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrl.svelte +2 -2
  18. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrlCalendar.svelte +1 -1
  19. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrlTimeFields.svelte +3 -3
  20. package/dist/components/FormerControllers/InlineWrapperPreview.svelte +18 -11
  21. package/dist/components/Gridler/components/Gridler.svelte +9 -4
  22. package/dist/components/Gridler/components/GridlerCanvas.svelte +4 -5
  23. package/dist/components/Gridler/components/GridlerFull.svelte +43 -33
  24. package/dist/components/Gridler/components/GridlerSearch.svelte +4 -2
  25. package/dist/components/Gridler/utils/canvasRender.js +4 -2
  26. package/dist/components/Gridler/utils/helpers.d.ts +16 -0
  27. package/dist/components/Gridler/utils/helpers.js +29 -0
  28. package/dist/components/Portal/Portal.svelte +1 -3
  29. package/dist/components/Svark/Svark.svelte +8 -1
  30. package/dist/components/Svark/SvarkTopBar.svelte +18 -18
  31. package/dist/components/SvarkGrid/SvarkGrid.svelte +1 -2
  32. package/dist/components/SvarkGrid/components/SvarkColumnFilterForm.svelte +2 -1
  33. package/dist/components/SvarkGrid/components/SvarkHeaderFilterCell.svelte +1 -1
  34. package/dist/components/SvarkGrid/utils/svarGridMapping.js +0 -1
  35. package/dist/components/VTree/VTreeResolveSpecAdapter.js +5 -10
  36. package/dist/css/kinathka.theme.css +205 -0
  37. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import type { Snippet } from 'svelte';
2
3
  import { getContext } from 'svelte';
3
4
  import type { BetterMenuInstanceItem, BetterMenuStoreState } from './types';
4
5
  import type { BetterMenuStore } from './store';
@@ -54,9 +55,9 @@
54
55
 
55
56
  {#snippet menuItem(item: BetterMenuInstanceItem, onClose: () => void)}
56
57
  {#if item.renderer}
57
- <div class="px-3 py-2">
58
- {@render (item.renderer as any)({ ...item, onClose })}
59
- </div>
58
+ <div class="px-3 py-2">
59
+ {@render (item.renderer as unknown as Snippet<[Record<string, unknown>]>)({ ...item, onClose })}
60
+ </div>
60
61
  {:else if item.isDivider}
61
62
  <hr class="border-slate-200 dark:border-slate-700 my-1" />
62
63
  {:else if item.onClick || item.onClickAsync}
@@ -100,10 +101,10 @@
100
101
  style:width={menuState.width ? `${menuState.width}px` : undefined}
101
102
  style:z-index={menuZ}
102
103
  >
103
- {#if menu.renderer}
104
- <div class="py-2">
105
- {@render (menu.renderer as any)({ id: menu.id, onClose: () => hideMenu(menu.id) })}
106
- </div>
104
+ {#if menu.renderer}
105
+ <div class="py-2">
106
+ {@render (menu.renderer as unknown as Snippet<[Record<string, unknown>]>)({ id: menu.id, onClose: () => hideMenu(menu.id) })}
107
+ </div>
107
108
  {:else}
108
109
  {#each menu.items ?? [] as item, itemIndex (`${menu.id}_item_${item.id ?? itemIndex}`)}
109
110
  {@render menuItem(item, () => hideMenu(menu.id))}
@@ -427,8 +427,8 @@
427
427
  });
428
428
 
429
429
  $effect(() => {
430
- anchorEl;
431
- storeOpened;
430
+ void anchorEl;
431
+ void storeOpened;
432
432
  syncInsideDialogFlag();
433
433
  });
434
434
 
@@ -493,8 +493,6 @@
493
493
  <Portal disabled={effectiveDisablePortal}>
494
494
  {#if $store.opened}
495
495
  {#if !effectiveDisablePortal}
496
- <!-- svelte-ignore a11y_click_events_have_key_events -->
497
- <!-- svelte-ignore a11y_no_static_element_interactions -->
498
496
  <div
499
497
  class="fixed inset-0"
500
498
  onpointerdown={onBackdropPointerDown}
@@ -19,6 +19,9 @@
19
19
  filename,
20
20
  contentType,
21
21
  mode = "value",
22
+ hideHeader = false,
23
+ theme,
24
+ colorScheme = "auto",
22
25
  readonly = false,
23
26
  onChange,
24
27
  onSave,
@@ -36,6 +39,7 @@
36
39
  }: ContentEditorProps = $props();
37
40
 
38
41
  const editorType = $derived(getEditorType({ filename, contentType }));
42
+ const forcedColorScheme = $derived(colorScheme === "auto" ? undefined : colorScheme);
39
43
 
40
44
  $effect(() => {
41
45
  if (mode === "filepointer") {
@@ -47,6 +51,8 @@
47
51
  </script>
48
52
 
49
53
  <div
54
+ data-theme={theme}
55
+ style:color-scheme={forcedColorScheme}
50
56
  style="display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 200px; overflow: hidden;"
51
57
  >
52
58
  {#if editorType === "monaco"}
@@ -67,7 +73,7 @@
67
73
  {:else if editorType === "video"}
68
74
  <VideoPlayer {value} {filename} />
69
75
  {:else if editorType === "text"}
70
- <TextEditor {value} {filename} {readonly} {onChange} bind:insertText bind:insertHtml />
76
+ <TextEditor {value} {filename} {hideHeader} {readonly} {onChange} bind:insertText bind:insertHtml />
71
77
  {:else if editorType === "markdown"}
72
78
  <MarkdownViewer {value} {filename} {readonly} {onChange} {onUpload} bind:insertText bind:insertHtml />
73
79
  {:else if editorType === "pdf"}
@@ -31,7 +31,6 @@
31
31
  {/if}
32
32
 
33
33
  {#if src}
34
- <!-- svelte-ignore a11y_media_has_caption -->
35
34
  <audio
36
35
  controls
37
36
  autoplay
@@ -13,7 +13,7 @@
13
13
  adminKey = "",
14
14
  userid = 0,
15
15
  username = "user",
16
- viewtype = "tabbed",
16
+ viewtype: _viewtype = "tabbed",
17
17
  headers,
18
18
  onChange,
19
19
  onSave,
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { ImageViewerProps } from '../types.js';
3
- let { value, filename }: ImageViewerProps = $props();
3
+ let { value: _value, filename }: ImageViewerProps = $props();
4
4
  </script>
5
5
 
6
6
  <div class="card p-4 text-surface-700-300">
@@ -14,12 +14,14 @@
14
14
  import '@cartamd/plugin-attachment/default.css';
15
15
  import 'katex/dist/katex.min.css';
16
16
  import 'github-markdown-css/github-markdown.css';
17
- import { blobToString } from '../utils.js';
17
+ import { blobToString, watchSkeletonDarkMode } from '../utils.js';
18
18
  import type { MarkdownViewerProps } from '../types.js';
19
19
 
20
20
  let { value, readonly = false, onChange, onUpload, insertText = $bindable(), insertHtml = $bindable() }: MarkdownViewerProps = $props();
21
21
 
22
22
  let carta = $state<Carta | undefined>(undefined);
23
+ let hostEl = $state<HTMLDivElement | undefined>(undefined);
24
+ let isDark = $state(false);
23
25
 
24
26
  onMount(() => {
25
27
  carta = new Carta({
@@ -34,6 +36,13 @@
34
36
  });
35
37
  });
36
38
 
39
+ onMount(() => {
40
+ const stopWatchingTheme = watchSkeletonDarkMode(hostEl, (nextIsDark) => {
41
+ isDark = nextIsDark;
42
+ });
43
+ return () => stopWatchingTheme();
44
+ });
45
+
37
46
  let text = $state('');
38
47
  let lastBlobText = $state('');
39
48
 
@@ -56,8 +65,18 @@
56
65
  insertHtml = undefined;
57
66
  return;
58
67
  }
68
+ type EditorViewLike = {
69
+ state: { selection: { main: { from: number; to: number } } };
70
+ dispatch: (payload: {
71
+ changes: { from: number; to: number; insert: string };
72
+ selection: { anchor: number };
73
+ }) => void;
74
+ focus: () => void;
75
+ };
76
+ type CartaEditorLike = Carta & { editor?: { editorView?: EditorViewLike } };
77
+
59
78
  function insertAtCursor(content: string): void {
60
- const view = carta!.editor?.editorView;
79
+ const view = (carta as CartaEditorLike).editor?.editorView;
61
80
  if (!view) return;
62
81
  const { from, to } = view.state.selection.main;
63
82
  view.dispatch({
@@ -71,7 +90,13 @@
71
90
  });
72
91
  </script>
73
92
 
74
- <div class="md-host" style="display: flex; flex-direction: column; width: 100%; height: 100%;">
93
+ <div
94
+ bind:this={hostEl}
95
+ class="md-host"
96
+ class:theme-dark={isDark}
97
+ class:theme-light={!isDark}
98
+ style="display: flex; flex-direction: column; width: 100%; height: 100%;"
99
+ >
75
100
  {#if carta}
76
101
  {#if readonly}
77
102
  {#key text}
@@ -110,8 +135,8 @@
110
135
  }
111
136
 
112
137
  /* Shiki dual-theme: dark colors only when .dark class is present */
113
- :global(.dark .shiki),
114
- :global(.dark .shiki span) {
138
+ :global(.md-host.theme-dark .shiki),
139
+ :global(.md-host.theme-dark .shiki span) {
115
140
  color: var(--shiki-dark) !important;
116
141
  background-color: var(--shiki-dark-bg) !important;
117
142
  font-style: var(--shiki-dark-font-style) !important;
@@ -120,7 +145,7 @@
120
145
  }
121
146
 
122
147
  /* carta-md dark mode: remap dark variable aliases when .dark is active */
123
- :global(.dark .carta-theme__default) {
148
+ :global(.md-host.theme-dark .carta-theme__default) {
124
149
  --border-color: var(--border-color-dark);
125
150
  --selection-color: var(--selection-color-dark);
126
151
  --focus-outline: var(--focus-outline-dark);
@@ -131,7 +156,7 @@
131
156
 
132
157
  /* github-markdown-css dark mode: override CSS vars when .dark class is active.
133
158
  github-markdown.css uses @media (prefers-color-scheme) which ignores the .dark class. */
134
- :global(.dark .markdown-body) {
159
+ :global(.md-host.theme-dark .markdown-body) {
135
160
  color-scheme: dark;
136
161
  --fgColor-default: #f0f6fc;
137
162
  --fgColor-muted: #9198a1;
@@ -186,7 +211,7 @@
186
211
  }
187
212
 
188
213
  /* github-markdown-css light mode: force light vars when OS may be dark but app is light */
189
- :global(html:not(.dark) .markdown-body) {
214
+ :global(.md-host.theme-light .markdown-body) {
190
215
  color-scheme: light;
191
216
  --fgColor-default: #1f2328;
192
217
  --fgColor-muted: #59636e;
@@ -1,7 +1,12 @@
1
1
  <script lang="ts">
2
2
  import { onMount } from 'svelte';
3
3
  import * as monaco from 'monaco-editor';
4
- import { getLangFromExt, getExtFromFilename, blobToString } from '../utils.js';
4
+ import {
5
+ getLangFromExt,
6
+ getExtFromFilename,
7
+ blobToString,
8
+ watchSkeletonDarkMode,
9
+ } from '../utils.js';
5
10
  import type { MonacoEditorProps } from '../types.js';
6
11
 
7
12
  let {
@@ -26,23 +31,9 @@
26
31
  );
27
32
 
28
33
  onMount(() => {
29
- // Dark mode detection priority: inline color-scheme style > .dark class > OS media query
30
- const mq = window.matchMedia('(prefers-color-scheme: dark)');
31
- const html = document.documentElement;
32
-
33
- function updateDark() {
34
- const explicit = html.style.colorScheme;
35
- if (explicit === 'dark' || explicit === 'light') {
36
- isDark = explicit === 'dark';
37
- } else {
38
- isDark = html.classList.contains('dark') || mq.matches;
39
- }
40
- }
41
-
42
- updateDark();
43
- mq.addEventListener('change', updateDark);
44
- const observer = new MutationObserver(updateDark);
45
- observer.observe(html, { attributeFilter: ['class', 'style'] });
34
+ const stopWatchingTheme = watchSkeletonDarkMode(container, (nextIsDark) => {
35
+ isDark = nextIsDark;
36
+ });
46
37
 
47
38
  editor = monaco.editor.create(container!, {
48
39
  value: '',
@@ -73,8 +64,7 @@
73
64
  insertHtml = (html: string) => doInsertText(html.replace(/<[^>]+>/g, ''));
74
65
 
75
66
  return () => {
76
- mq.removeEventListener('change', updateDark);
77
- observer.disconnect();
67
+ stopWatchingTheme();
78
68
  insertText = undefined;
79
69
  insertHtml = undefined;
80
70
  editor?.dispose();
@@ -2,6 +2,7 @@
2
2
  import { onMount, untrack, tick } from "svelte";
3
3
  import type { Office365EditorProps } from "../types.js";
4
4
  import { getExtFromFilename } from "../utils.js";
5
+ import { SvelteURLSearchParams } from "svelte/reactivity";
5
6
 
6
7
  let {
7
8
  value,
@@ -71,7 +72,8 @@
71
72
  // ── WOPI helpers ─────────────────────────────────────────────────────────────
72
73
 
73
74
  async function fileExistsInWopi(token: string): Promise<boolean> {
74
- const params = new URLSearchParams({ access_token: token });
75
+ const params = new SvelteURLSearchParams();
76
+ params.append("access_token", token);
75
77
  const base = wopiUrl.replace(/\/$/, "");
76
78
  const res = await fetch(`${base}/wopi/files/${fileId}/contents?${params}`, {
77
79
  headers,
@@ -81,7 +83,8 @@
81
83
  }
82
84
 
83
85
  async function uploadToWopi(blob: Blob, token: string): Promise<void> {
84
- const params = new URLSearchParams({ access_token: token });
86
+ const params = new SvelteURLSearchParams();
87
+ params.append("access_token", token);
85
88
  if (filename !== undefined) params.append("filename", filename);
86
89
  const base = wopiUrl.replace(/\/$/, "");
87
90
  const res = await fetch(`${base}/wopi/files/${fileId}/contents?${params}`, {
@@ -93,7 +96,8 @@
93
96
  }
94
97
 
95
98
  async function downloadFromWopi(): Promise<Blob | undefined> {
96
- const params = new URLSearchParams({ access_token: signedToken });
99
+ const params = new SvelteURLSearchParams();
100
+ params.append("access_token", signedToken);
97
101
  const base = wopiUrl.replace(/\/$/, "");
98
102
  const res = await fetch(`${base}/wopi/files/${fileId}/contents?${params}`, {
99
103
  headers,
@@ -36,14 +36,13 @@
36
36
  >
37
37
  <div class="flex h-full w-full flex-col items-center justify-center gap-3 p-6 text-center text-surface-700-300">
38
38
  <p class="text-sm opacity-70">This browser could not display the PDF inline.</p>
39
- <a
40
- href={src}
41
- target="_blank"
42
- rel="noopener noreferrer"
39
+ <button
40
+ type="button"
43
41
  class="btn variant-outline"
42
+ onclick={() => window.open(src, '_blank', 'noopener,noreferrer')}
44
43
  >
45
44
  Open PDF in new tab
46
- </a>
45
+ </button>
47
46
  </div>
48
47
  </object>
49
48
  {:else}