@djcali570/component-lib 0.1.9 → 0.1.92

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.
@@ -34,10 +34,6 @@
34
34
  // svelte-ignore state_referenced_locally
35
35
  const colorScheme = { ...defaultColorScheme, ...partialColorScheme };
36
36
  const id = `checkbox-${Math.random().toString(36).slice(2, 8)}`;
37
-
38
- $effect(() => {
39
- onChange(checked);
40
- });
41
37
  </script>
42
38
 
43
39
  <div
@@ -51,7 +47,19 @@
51
47
  "
52
48
  >
53
49
  <label for={id}>
54
- <input type="checkbox" {id} {name} bind:checked {disabled} />
50
+ <input
51
+ type="checkbox"
52
+ {id}
53
+ {name}
54
+ {checked}
55
+ {disabled}
56
+ onchange={(e) => {
57
+ const value = (e.target as HTMLInputElement).checked;
58
+ checked = value;
59
+ onChange(value);
60
+ }}
61
+ />
62
+
55
63
  <span class="air5__checkbox__custom">
56
64
  {#if checked}
57
65
  <svg viewBox="0 0 24 24">
@@ -87,6 +95,8 @@
87
95
  display: flex;
88
96
  align-items: center;
89
97
  cursor: pointer;
98
+ /* REMOVE mobile tap highlight */
99
+ -webkit-tap-highlight-color: transparent;
90
100
  }
91
101
 
92
102
  .air5__checkbox__custom {
@@ -0,0 +1,190 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import type { Snippet } from 'svelte';
4
+ import type { ContextMenu5ColorScheme } from './types.js';
5
+ import { fly } from 'svelte/transition';
6
+
7
+ // Props
8
+ let {
9
+ icon,
10
+ content,
11
+ colorScheme: partialColorScheme = {},
12
+ ariaLabel = 'Open context menu',
13
+ menuAlign = 'right',
14
+ open = $bindable()
15
+ }: {
16
+ icon?: Snippet;
17
+ content: Snippet;
18
+ colorScheme?: Partial<ContextMenu5ColorScheme>;
19
+ ariaLabel?: string;
20
+ menuAlign?: 'left' | 'right';
21
+ open?: boolean;
22
+ } = $props();
23
+
24
+ // Default colors
25
+ const defaultColorScheme: ContextMenu5ColorScheme = {
26
+ contentBgColor: '#121212',
27
+ contentBorderColor: '#191919',
28
+ iconFillColor: '#121212',
29
+ iconBorderColor: '#121212',
30
+ iconColor: '#F5F5F5'
31
+ };
32
+ const colorScheme = $derived({
33
+ ...defaultColorScheme,
34
+ ...partialColorScheme
35
+ });
36
+
37
+ // DOM refs
38
+ let triggerEl: HTMLElement | null = null;
39
+ let menuEl: HTMLElement | null = $state(null);
40
+
41
+ // Toggle menu
42
+ function toggle() {
43
+ open = !open;
44
+ }
45
+
46
+ // Close menu
47
+ function closeMenu() {
48
+ open = false;
49
+ }
50
+
51
+ // Click outside
52
+ function handlePointerDown(e: PointerEvent) {
53
+ if (!open) return;
54
+
55
+ const target = e.target as Node;
56
+ if (menuEl && triggerEl && !menuEl.contains(target) && !triggerEl.contains(target)) {
57
+ closeMenu();
58
+ }
59
+ }
60
+
61
+ // Escape key
62
+ function handleKeyDown(e: KeyboardEvent) {
63
+ if (e.key === 'Escape') closeMenu();
64
+ }
65
+
66
+ onMount(() => {
67
+ document.addEventListener('pointerdown', handlePointerDown);
68
+ document.addEventListener('keydown', handleKeyDown);
69
+
70
+ return () => {
71
+ document.removeEventListener('pointerdown', handlePointerDown);
72
+ document.removeEventListener('keydown', handleKeyDown);
73
+ };
74
+ });
75
+ </script>
76
+
77
+ <div
78
+ class="context5"
79
+ style="
80
+ --context5__ContentBgColor: {colorScheme.contentBgColor};
81
+ --context5__ContentBorderColor: {colorScheme.contentBorderColor};
82
+ --context5__IconBorderColor: {colorScheme.iconBorderColor};
83
+ --context5__IconColor: {colorScheme.iconColor};
84
+ --context5__IconFillColor: {colorScheme.iconFillColor};
85
+ "
86
+ >
87
+ <button
88
+ aria-label={ariaLabel}
89
+ type="button"
90
+ aria-haspopup="menu"
91
+ aria-expanded={open}
92
+ bind:this={triggerEl}
93
+ onclick={toggle}
94
+ class="context5__btn"
95
+ >
96
+ {#if icon}
97
+ <div class="context5__icon">
98
+ {@render icon()}
99
+ </div>
100
+ {:else}
101
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
102
+ <circle cx="12" cy="5" r="2" />
103
+ <circle cx="12" cy="12" r="2" />
104
+ <circle cx="12" cy="19" r="2" />
105
+ </svg>
106
+ {/if}
107
+ </button>
108
+
109
+ {#if open}
110
+ <div
111
+ bind:this={menuEl}
112
+ role="menu"
113
+ class="context5__menu"
114
+ class:left={menuAlign === 'left'}
115
+ class:right={menuAlign === 'right'}
116
+ transition:fly={{ y: 10 }}
117
+ >
118
+ <div class="context5__content">
119
+ {@render content()}
120
+ </div>
121
+ </div>
122
+ {/if}
123
+ </div>
124
+
125
+ <style>
126
+ .context5 {
127
+ position: relative;
128
+ display: inline-block;
129
+ }
130
+
131
+ .context5__icon {
132
+ width: 20px;
133
+ height: 20px;
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ flex-shrink: 0;
138
+ }
139
+
140
+ /* force ANY svg inside to obey the container */
141
+ .context5__icon :global(*) {
142
+ width: 100% !important;
143
+ height: 100% !important;
144
+ display: block;
145
+ }
146
+
147
+ .context5__btn {
148
+ width: 30px; /* set width */
149
+ height: 30px; /* set height (same as width for a perfect circle) */
150
+ padding: 0; /* remove extra padding */
151
+ border-radius: 50%; /* fully round */
152
+ cursor: pointer;
153
+ background-color: var(--context5__IconFillColor);
154
+ border: none;
155
+ outline: none;
156
+ -webkit-tap-highlight-color: transparent; /* removes blue flash on touch devices */
157
+ display: flex; /* center the icon inside */
158
+ align-items: center;
159
+ justify-content: center;
160
+ border: 1px solid var(--context5__IconBorderColor);
161
+ }
162
+
163
+ .context5__btn > svg {
164
+ color: var(--context5__IconColor);
165
+ }
166
+
167
+ .context5__menu {
168
+ position: absolute;
169
+ margin-top: 0.5rem;
170
+ z-index: 1000;
171
+ transform-origin: top;
172
+ }
173
+
174
+ .context5__menu.right {
175
+ right: 0;
176
+ transform-origin: top right;
177
+ }
178
+
179
+ .context5__menu.left {
180
+ left: 0;
181
+ transform-origin: top left;
182
+ }
183
+
184
+ .context5__content {
185
+ background-color: var(--context5__ContentBgColor);
186
+ border-radius: 0.5rem;
187
+ padding: 0.5rem;
188
+ border: 1px solid var(--context5__ContentBorderColor);
189
+ }
190
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { ContextMenu5ColorScheme } from './types.js';
3
+ type $$ComponentProps = {
4
+ icon?: Snippet;
5
+ content: Snippet;
6
+ colorScheme?: Partial<ContextMenu5ColorScheme>;
7
+ ariaLabel?: string;
8
+ menuAlign?: 'left' | 'right';
9
+ open?: boolean;
10
+ };
11
+ declare const ContextMenu5: import("svelte").Component<$$ComponentProps, {}, "open">;
12
+ type ContextMenu5 = ReturnType<typeof ContextMenu5>;
13
+ export default ContextMenu5;
@@ -1,12 +1,8 @@
1
1
  <script lang="ts">
2
- import { browser } from '$app/environment';
2
+ import { BROWSER } from 'esm-env';
3
3
  import { fly } from 'svelte/transition';
4
4
  import type { DatePicker5ColorScheme } from './types.js';
5
5
 
6
- /**
7
- * Date Picker 5 v0.0.1
8
- */
9
-
10
6
  let {
11
7
  colorScheme: partialColorScheme = {},
12
8
  title = '',
@@ -123,7 +119,7 @@
123
119
 
124
120
  // Close dropdown when clicking outside
125
121
  $effect(() => {
126
- if (!browser || !showDropdown) return;
122
+ if (!BROWSER || !showDropdown) return;
127
123
 
128
124
  const handleClickOutside = (event: MouseEvent) => {
129
125
  const target = event.target as Node;
@@ -149,7 +145,7 @@
149
145
  // Auto-scroll to make dropdown fully visible
150
146
 
151
147
  $effect(() => {
152
- if (!browser || !showDropdown || !dropdownRef) return;
148
+ if (!BROWSER || !showDropdown || !dropdownRef) return;
153
149
  setTimeout(() => {
154
150
  if (!dropdownRef) return;
155
151
  const dropdownRect = dropdownRef.getBoundingClientRect();
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { browser } from '$app/environment';
2
+ import { BROWSER } from 'esm-env';
3
3
  import { onDestroy, onMount } from 'svelte';
4
4
  import { fly } from 'svelte/transition';
5
5
  import type { DropDown5ColorScheme, DropDownItem } from './types.js';
@@ -47,7 +47,7 @@
47
47
  let filteredItems: DropDownItem[] = $state([]);
48
48
 
49
49
  $effect(() => {
50
- if (!browser || !showDropdown || !dropdownRef) return;
50
+ if (!BROWSER || !showDropdown || !dropdownRef) return;
51
51
  setTimeout(() => {
52
52
  if (!dropdownRef) return;
53
53
  const dropdownRect = dropdownRef.getBoundingClientRect();
@@ -2,14 +2,6 @@
2
2
  import { onMount } from 'svelte';
3
3
  import type { Input5ColorScheme } from './types.js';
4
4
 
5
- /**
6
- * Input5 v0.0.2
7
- *
8
- * Added color scheme partials
9
- * Added read only option
10
- * Allow 4 digits after decimal for floats
11
- */
12
-
13
5
  let {
14
6
  colorScheme: partialColorScheme = {},
15
7
  name = 'input',
@@ -25,6 +17,8 @@
25
17
  textArea = false,
26
18
  textAreaHeight = 80,
27
19
  readonly = false,
20
+ placeholder = '',
21
+ hideTitle = false,
28
22
  onUpdate = (value) => {}
29
23
  }: {
30
24
  colorScheme?: Partial<Input5ColorScheme>;
@@ -41,6 +35,8 @@
41
35
  textArea?: boolean;
42
36
  textAreaHeight?: number;
43
37
  readonly?: boolean | null | undefined;
38
+ placeholder?: string;
39
+ hideTitle?: boolean;
44
40
  onUpdate?: (value: string) => void;
45
41
  } = $props();
46
42
 
@@ -53,10 +49,12 @@
53
49
  clearColor: '#989A9A',
54
50
  clearHoverColor: '#1F2023',
55
51
  counterTextColor: '#5ac1dd',
56
- counterBgColor: '#1F2023'
52
+ counterBgColor: '#1F2023',
53
+ placeholderColor: '#989A9A'
57
54
  };
58
55
 
59
56
  // Merge partial colorScheme with defaults
57
+ // svelte-ignore state_referenced_locally
60
58
  const colorScheme = { ...defaultColorScheme, ...partialColorScheme };
61
59
 
62
60
  const id = generateRandomString();
@@ -161,6 +159,7 @@
161
159
  * Assign function to validator
162
160
  */
163
161
  if (
162
+ // svelte-ignore state_referenced_locally
164
163
  validator === 'float' ||
165
164
  validator === 'number' ||
166
165
  validator === 'phone' ||
@@ -169,22 +168,23 @@
169
168
  keydownHandler = mainKeyDownHandler;
170
169
  }
171
170
 
171
+ // svelte-ignore state_referenced_locally
172
172
  if (validator === 'float') {
173
173
  inputHandler = (e: Event) => mainInputInputHandler(e, floatPattern);
174
174
  }
175
-
175
+ // svelte-ignore state_referenced_locally
176
176
  if (validator === 'number') {
177
177
  inputHandler = (e: Event) => mainInputInputHandler(e, numberOnlyPattern);
178
178
  }
179
-
179
+ // svelte-ignore state_referenced_locally
180
180
  if (validator === 'phone') {
181
181
  inputHandler = (e: Event) => mainInputInputHandler(e, phoneNumberPattern);
182
182
  }
183
-
183
+ // svelte-ignore state_referenced_locally
184
184
  if (validator === 'phone') {
185
185
  inputHandler = (e: Event) => mainInputInputHandler(e, phoneNumberPattern);
186
186
  }
187
-
187
+ // svelte-ignore state_referenced_locally
188
188
  if (validator === 'letter') {
189
189
  inputHandler = (e: Event) => mainInputInputHandler(e, letterOnlyPattern);
190
190
  }
@@ -225,11 +225,16 @@
225
225
  --air5__counterTextColor: {colorScheme.counterTextColor};
226
226
  --air5__counterBgColor: {colorScheme.counterBgColor};
227
227
  --air5__textAreaHeight: {textAreaHeight}px;
228
+ --air5__placeholderColor: {colorScheme.placeholderColor};
228
229
  "
229
230
  >
230
231
  <label for="input-{id}">
231
232
  <div>
232
- <div class="air5__title">{title}</div>
233
+ {#if !hideTitle}
234
+ <div class="air5__title">{title}</div>
235
+ {:else}
236
+ <div class="air5__title">&nbsp;</div>
237
+ {/if}
233
238
  <div class="air5__input">
234
239
  {#if textArea}
235
240
  <textarea
@@ -241,6 +246,7 @@
241
246
  {maxlength}
242
247
  {autocomplete}
243
248
  {readonly}
249
+ {placeholder}
244
250
  ></textarea>
245
251
  {:else}
246
252
  <input
@@ -253,6 +259,7 @@
253
259
  {autocomplete}
254
260
  {type}
255
261
  {readonly}
262
+ {placeholder}
256
263
  />
257
264
  {/if}
258
265
  <div class="air5__options__container">
@@ -327,7 +334,7 @@
327
334
 
328
335
  .air5__input {
329
336
  display: grid;
330
- grid-template-columns: 1fr min-content;
337
+ grid-template-columns: 1fr min-content;
331
338
  padding-inline: 0.75rem;
332
339
  color: var(--air5__mainTextColor);
333
340
  }
@@ -415,4 +422,10 @@
415
422
  color: var(--air5__counterTextColor);
416
423
  background-color: var(--air5__counterBgColor);
417
424
  }
425
+
426
+ input::placeholder,
427
+ textarea::placeholder {
428
+ color: var(--air5__placeholderColor);
429
+ opacity: 1; /* ensures color is fully visible across browsers */
430
+ }
418
431
  </style>
@@ -14,6 +14,8 @@ type $$ComponentProps = {
14
14
  textArea?: boolean;
15
15
  textAreaHeight?: number;
16
16
  readonly?: boolean | null | undefined;
17
+ placeholder?: string;
18
+ hideTitle?: boolean;
17
19
  onUpdate?: (value: string) => void;
18
20
  };
19
21
  declare const Input5: import("svelte").Component<$$ComponentProps, {}, "value">;
package/dist/index.d.ts CHANGED
@@ -6,8 +6,9 @@ import Accordion5 from "./Accordion5.svelte";
6
6
  import Chart5 from "./Chart5.svelte";
7
7
  import AdminPanel5 from "./AdminPanel5.svelte";
8
8
  import Checkbox5 from "./Checkbox5.svelte";
9
- import type { Input5ColorScheme, DatePicker5ColorScheme, TimePicker5ColorScheme, DropDownItem, DropDown5ColorScheme, Accordion5ColorScheme, Chart5ColorScheme, AdminPanel5ColorScheme, BottomSheet5ColorScheme, Dialog5ColorScheme, Checkbox5ColorScheme } from "./types.js";
9
+ import ContextMenu5 from "./ContextMenu5.svelte";
10
+ import type { Input5ColorScheme, DatePicker5ColorScheme, TimePicker5ColorScheme, DropDownItem, DropDown5ColorScheme, Accordion5ColorScheme, Chart5ColorScheme, AdminPanel5ColorScheme, BottomSheet5ColorScheme, Dialog5ColorScheme, Checkbox5ColorScheme, ContextMenu5ColorScheme } from "./types.js";
10
11
  import BottomSheet5 from "./BottomSheet5.svelte";
11
12
  import Dialog5 from "./Dialog5.svelte";
12
- export { DatePicker5, Input5, DropDown5, TimePicker5, Accordion5, Chart5, AdminPanel5, BottomSheet5, Dialog5, Checkbox5 };
13
- export type { Input5ColorScheme, DatePicker5ColorScheme, TimePicker5ColorScheme, Accordion5ColorScheme, DropDown5ColorScheme, DropDownItem, Chart5ColorScheme, AdminPanel5ColorScheme, BottomSheet5ColorScheme, Dialog5ColorScheme, Checkbox5ColorScheme };
13
+ export { DatePicker5, Input5, DropDown5, TimePicker5, Accordion5, Chart5, AdminPanel5, BottomSheet5, Dialog5, Checkbox5, ContextMenu5 };
14
+ export type { Input5ColorScheme, DatePicker5ColorScheme, TimePicker5ColorScheme, Accordion5ColorScheme, DropDown5ColorScheme, DropDownItem, Chart5ColorScheme, AdminPanel5ColorScheme, BottomSheet5ColorScheme, Dialog5ColorScheme, Checkbox5ColorScheme, ContextMenu5ColorScheme };
package/dist/index.js CHANGED
@@ -9,4 +9,5 @@ import AdminPanel5 from "./AdminPanel5.svelte";
9
9
  import BottomSheet5 from "./BottomSheet5.svelte";
10
10
  import Dialog5 from "./Dialog5.svelte";
11
11
  import Checkbox5 from "./Checkbox5.svelte";
12
- export { DatePicker5, Input5, DropDown5, TimePicker5, Accordion5, Chart5, AdminPanel5, BottomSheet5, Dialog5, Checkbox5 };
12
+ import ContextMenu5 from "./ContextMenu5.svelte"
13
+ export { DatePicker5, Input5, DropDown5, TimePicker5, Accordion5, Chart5, AdminPanel5, BottomSheet5, Dialog5, Checkbox5, ContextMenu5 };
package/dist/types.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface Input5ColorScheme {
9
9
  clearHoverColor?: string;
10
10
  counterTextColor?: string;
11
11
  counterBgColor?: string;
12
+ placeholderColor?: string;
12
13
  }
13
14
  export interface DatePicker5ColorScheme {
14
15
  labelTextColor?: string;
@@ -97,3 +98,11 @@ export interface Checkbox5ColorScheme {
97
98
  focusedColor?: string;
98
99
  checkmarkColor?: string;
99
100
  }
101
+
102
+ export interface ContextMenu5ColorScheme {
103
+ contentBgColor?: string;
104
+ contentBorderColor?: string;
105
+ iconFillColor?: string;
106
+ iconBorderColor?: string;
107
+ iconColor?: string;
108
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djcali570/component-lib",
3
- "version": "0.1.9",
3
+ "version": "0.1.92",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/*.test.*",
@@ -19,6 +19,7 @@
19
19
  }
20
20
  },
21
21
  "peerDependencies": {
22
+ "@sveltejs/kit": "^2.50.2",
22
23
  "svelte": "^5.0.0"
23
24
  },
24
25
  "devDependencies": {
@@ -60,5 +61,8 @@
60
61
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
61
62
  "format": "prettier --write .",
62
63
  "lint": "prettier --check . && eslint ."
64
+ },
65
+ "dependencies": {
66
+ "esm-env": "^1.2.2"
63
67
  }
64
68
  }