@hkdigital/lib-core 0.4.4 → 0.4.6

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 CHANGED
@@ -9,39 +9,120 @@ It contains common code, base components and documentation that help you with se
9
9
 
10
10
  ### Install
11
11
 
12
- The library can be installed as a normal NPM library.
13
-
12
+ **For projects/applications:**
14
13
  ```bash
15
14
  pnpm add @hkdigital/lib-core
16
15
  ```
17
16
 
18
- ### Peer Dependencies
19
-
20
- This library requires certain peer dependencies depending on which features you use:
21
-
22
- **For development logging:**
23
- ```bash
24
- pnpm add -D pino-pretty
25
- ```
26
-
27
- **For Vite config generators with imagetools:**
17
+ **For other libraries:**
28
18
  ```bash
29
- pnpm add -D vite-imagetools
19
+ pnpm add -D --save-peer @hkdigital/lib-core
30
20
  ```
31
21
 
32
- #### Tailwind
33
-
34
- Components in this package use [tailwindcss](https://tailwindcss.com/).
35
-
36
- To compile tailwind classes inside this package, you must add the package location to your tailwindcss plugin configuration.
22
+ ### Peer Dependencies
37
23
 
38
- ```
39
- // tailwind.config.js
40
- export default {
41
- content: [
42
- './node_modules/@hkdigital/**/*.{html,js,svelte,ts}',
43
- './src/**/*.{html,js,svelte,ts}',
44
- ```
24
+ Install peer dependencies:
25
+ ```bash
26
+ # Core framework and utilities
27
+ pnpm add @sveltejs/kit svelte svelte-preprocess runed valibot
28
+
29
+ # UI components and icons
30
+ pnpm add @steeze-ui/heroicons
31
+
32
+ # Logging
33
+ pnpm add pino pino-pretty
34
+
35
+ # Linting
36
+ pnpm add @eslint/js eslint-plugin-import
37
+ ```
38
+
39
+ ### Design System & Configuration
40
+
41
+ This library includes a complete design system with Tailwind CSS integration. Basic setup requires:
42
+
43
+ 1. **Tailwind config** - Include library files in content scanning:
44
+ ```js
45
+ // tailwind.config.js
46
+ import {
47
+ generateTailwindThemeExtensions,
48
+ designTokens,
49
+ customUtilitiesPlugin
50
+ } from '@hkdigital/lib-core/design/index.js';
51
+
52
+ const themeExtensions = generateTailwindThemeExtensions(designTokens);
53
+
54
+ /** @type {import('tailwindcss').Config} */
55
+ export default {
56
+ // Include @hkdigital libraries in content so Tailwind processes
57
+ // their design system classes and components for proper styling
58
+ content: [
59
+ './node_modules/@hkdigital/**/*.{html,js,svelte}',
60
+ './src/**/*.{html,js,svelte}'
61
+ ],
62
+ theme: {
63
+ // Extend Tailwind's default theme using the design system tokens
64
+ extend: themeExtensions
65
+ },
66
+ plugins: [
67
+ // Generate custom utility classes like 'type-heading-h2'
68
+ customUtilitiesPlugin
69
+ ]
70
+ };
71
+ ```
72
+
73
+ 2. **Design tokens** - Apply CSS variables in your layout:
74
+ ```html
75
+ <!-- src/routes/+layout.svelte -->
76
+ <script>
77
+ import { designTokens, designTokensToRootCssVars } from '@hkdigital/lib-core/design/index.js';
78
+ </script>
79
+
80
+ <svelte:head>
81
+ {@html designTokensToRootCssVars(designTokens)}
82
+ </svelte:head>
83
+
84
+ {@render children()}
85
+ ```
86
+
87
+ 3. **Vite configuration** - Use the provided config generator:
88
+ ```js
89
+ // vite.config.js
90
+ import { defineConfig } from 'vitest/config';
91
+ import { generateViteConfig } from '@hkdigital/lib-core/config/vite.js';
92
+
93
+ export default defineConfig(
94
+ await generateViteConfig({
95
+ enableImagetools: true,
96
+ enableVitest: true
97
+ })
98
+ );
99
+ ```
100
+
101
+ 4. **Svelte configuration** - Configure preprocessing and useful path aliases:
102
+ ```js
103
+ // svelte.config.js
104
+ import { sveltePreprocess } from 'svelte-preprocess';
105
+ import adapter from '@sveltejs/adapter-auto';
106
+
107
+ /** @type {import('@sveltejs/kit').Config} */
108
+ const config = {
109
+ // Enable preprocessing for external CSS files in Svelte components
110
+ preprocess: sveltePreprocess({}),
111
+ kit: {
112
+ adapter: adapter(),
113
+ alias: {
114
+ $src: 'src',
115
+ $examples: 'src/routes/examples'
116
+ }
117
+ }
118
+ };
119
+
120
+ export default config;
121
+ ```
122
+
123
+ For detailed setup guides see:
124
+ - **Design system**: [src/lib/design/README.md](./src/lib/design/README.md)
125
+ - **Vite configuration**: [src/lib/config/README.md](./src/lib/config/README.md)
45
126
 
46
127
  ### Update
47
128
 
@@ -52,40 +133,18 @@ in the '@hkdigital' namespace.
52
133
  pnpm upgrade:hk
53
134
  ```
54
135
 
55
- ### The package.json scripts:
136
+ ### Available scripts
56
137
 
57
138
  ```bash
58
- pnpm add -D npm-check-updates
59
- pnpm add -D npm-check-updates
139
+ pnpm run dev # Start development server
140
+ pnpm run build # Build the library
141
+ pnpm run check # Type checking and validation
142
+ pnpm run test # Run unit tests
143
+ pnpm run upgrade:hk # Update all @hkdigital/... packages
144
+ pnpm run upgrade:all # Update all packages
145
+ pnpm run publish:npm # Version bump and publish to npm
60
146
  ```
61
147
 
62
- ```js
63
- "scripts": {
64
- "upgrade:hk": "run-s upgrade:hk:update pnpm:install",
65
- "upgrade:hk:update": "ncu --dep dev,optional,peer,prod '@hkdigital/*' -u",
66
- "pnpm:install": "pnpm install"
67
- }
68
- ```
69
-
70
- ### Vite Configuration
71
-
72
- The library provides configuration generators for Vite that include common HKdigital project settings:
73
-
74
- ```javascript
75
- // vite.config.js
76
- import { defineConfig } from 'vitest/config';
77
- import { generateViteConfig } from '@hkdigital/lib-core/config/vite.js';
78
-
79
- export default defineConfig(
80
- await generateViteConfig({
81
- enableImagetools: true,
82
- enableVitest: true
83
- })
84
- );
85
- ```
86
-
87
- For detailed configuration options, see the [config documentation](./src/lib/config/README.md).
88
-
89
148
  ### Import JS, Svelte files and Typedefs
90
149
 
91
150
  Main folders in lib have an index.js, but may also have a more specific export file e.g. http.js or cache.js (@see $lib/network).
@@ -114,18 +173,6 @@ For example:
114
173
  @import '../node_modules/@hkdigital/lib-core/dist/css/utilities.css';
115
174
  ```
116
175
 
117
- ### Enable tailwind processing
118
-
119
- Allow the tailwind CSS processor to work on the library inside node_modules
120
-
121
- ```js
122
- // tailwind.config.js
123
- export default {
124
- content: [
125
- './node_modules/@hkdigital/**/*.{html,js,svelte,ts}',
126
- './src/**/*.{html,js,svelte,ts}',
127
- ```
128
-
129
176
  ## Building the library
130
177
 
131
178
  To build your library:
@@ -56,51 +56,21 @@ export default defineConfig(
56
56
  );
57
57
  ```
58
58
 
59
- #### `generateViteDefines(options)`
60
-
61
- Generates only the define configuration (no plugins).
62
-
63
- **Options:**
64
- - `packageJsonPath` (string, default: `'./package.json'`) - Path to package.json
65
- - `customDefines` (object, default: `{}`) - Additional define values
66
-
67
- **Example:**
68
- ```javascript
69
- export default defineConfig({
70
- plugins: [sveltekit()],
71
- define: generateViteDefines({
72
- customDefines: {
73
- 'import.meta.env.VITE_API_URL': JSON.stringify(process.env.API_URL)
74
- }
75
- })
76
- });
77
- ```
78
-
79
- #### `generateVitestConfig(options)`
80
-
81
- Generates only the Vitest test configuration.
82
-
83
- **Options:**
84
- - `additionalPatterns` (array, default: `[]`) - Additional test file patterns
85
-
86
- **Example:**
87
- ```javascript
88
- export default defineConfig({
89
- plugins: [sveltekit()],
90
- test: generateVitestConfig({
91
- additionalPatterns: ['tests/**/*.integration.js']
92
- })
93
- });
94
- ```
95
59
 
96
60
  ## Imagetools Configuration
97
61
 
98
- When `enableImagetools: true`, the following dependencies are required in your project:
62
+ When `enableImagetools: true`, install the imagetools dependency:
99
63
 
64
+ **For projects/applications:**
100
65
  ```bash
101
66
  pnpm add -D vite-imagetools
102
67
  ```
103
68
 
69
+ **For other libraries:**
70
+ ```bash
71
+ pnpm add -D --save-peer vite-imagetools
72
+ ```
73
+
104
74
  ### TypeScript Support
105
75
 
106
76
  For TypeScript and JavaScript projects using VS Code or other TypeScript-aware editors, add to your `app.d.ts`:
@@ -1 +1 @@
1
- export { generateViteConfig, generateViteDefines, generateVitestConfig } from "./generators/vite.js";
1
+ export { generateViteConfig } from "./generators/vite.js";
@@ -1,5 +1,3 @@
1
1
  export {
2
- generateViteConfig,
3
- generateViteDefines,
4
- generateVitestConfig
2
+ generateViteConfig
5
3
  } from './generators/vite.js';
@@ -0,0 +1,300 @@
1
+ <script>
2
+ import { goto } from '$app/navigation';
3
+
4
+ /**
5
+ * Reusable explorer component for navigating nested folder structures
6
+ * @type {{
7
+ * navigationData: Object,
8
+ * currentPath: string,
9
+ * getActiveSegments?: (segments: string[]) => void,
10
+ * getNavigateToLevelFunction?: (fn: Function) => void,
11
+ * rootName?: string,
12
+ * folderName?: string
13
+ * }}
14
+ */
15
+ let {
16
+ navigationData,
17
+ currentPath = '',
18
+ getActiveSegments,
19
+ getNavigateToLevelFunction,
20
+ rootName = 'Categories',
21
+ folderName
22
+ } = $props();
23
+
24
+ /** @type {string[]} */
25
+ let pathSegments = $derived(
26
+ currentPath ? currentPath.split('/').filter(Boolean) : []
27
+ );
28
+
29
+ /** @type {string[]} */
30
+ let interactiveSegments = $state([]);
31
+
32
+ /** @type {string[]} */
33
+ let activeSegments = $derived(
34
+ interactiveSegments.length > 0 ? interactiveSegments : pathSegments
35
+ );
36
+
37
+ // Notify parent of active segments changes - only when they change
38
+ let lastActiveSegments = [];
39
+ $effect(() => {
40
+ if (
41
+ getActiveSegments &&
42
+ JSON.stringify(activeSegments) !== JSON.stringify(lastActiveSegments)
43
+ ) {
44
+ lastActiveSegments = [...activeSegments];
45
+ getActiveSegments(activeSegments);
46
+ }
47
+ });
48
+
49
+ /** @type {Object[]} */
50
+ let breadcrumbColumns = $derived.by(() => {
51
+ const columns = [];
52
+ let current = navigationData;
53
+
54
+ // Root column with sorted items (folders first, then endpoints)
55
+ const rootItems = Object.values(current).map((item) => ({
56
+ name: item.name,
57
+ displayName: item.displayName || item.name,
58
+ isEndpoint: item.isEndpoint,
59
+ isSelected: activeSegments.length > 0 &&
60
+ activeSegments[0] === item.name
61
+ })).sort((a, b) => {
62
+ // Sort by type first (folders before endpoints)
63
+ if (a.isEndpoint !== b.isEndpoint) {
64
+ return a.isEndpoint ? 1 : -1;
65
+ }
66
+ // Then sort alphabetically by display name
67
+ return a.displayName.localeCompare(b.displayName);
68
+ });
69
+
70
+ columns.push({
71
+ title: rootName,
72
+ items: rootItems,
73
+ level: 0
74
+ });
75
+
76
+ // Build columns for each path segment
77
+ for (let i = 0; i < activeSegments.length; i++) {
78
+ const segment = activeSegments[i];
79
+
80
+ if (current[segment]) {
81
+ current = current[segment].children;
82
+
83
+ if (Object.keys(current).length > 0) {
84
+ const nextSegment = activeSegments[i + 1];
85
+
86
+ // Sort nested items (folders first, then endpoints)
87
+ const nestedItems = Object.values(current).map((item) => ({
88
+ name: item.name,
89
+ displayName: item.displayName || item.name,
90
+ isEndpoint: item.isEndpoint,
91
+ isSelected: nextSegment === item.name
92
+ })).sort((a, b) => {
93
+ // Sort by type first (folders before endpoints)
94
+ if (a.isEndpoint !== b.isEndpoint) {
95
+ return a.isEndpoint ? 1 : -1;
96
+ }
97
+ // Then sort alphabetically by display name
98
+ return a.displayName.localeCompare(b.displayName);
99
+ });
100
+
101
+ columns.push({
102
+ title: segment,
103
+ items: nestedItems,
104
+ level: i + 1
105
+ });
106
+ }
107
+ }
108
+ }
109
+
110
+ return columns;
111
+ });
112
+
113
+ /**
114
+ * Handle navigation to a folder or endpoint
115
+ * @param {number} level - Column level
116
+ * @param {string} itemName - Item name
117
+ * @param {boolean} isEndpoint - Whether this is a final endpoint
118
+ */
119
+ function handleNavigation(level, itemName, isEndpoint) {
120
+ // Build new path segments up to the selected level
121
+ const newSegments = [...activeSegments.slice(0, level), itemName];
122
+ const fullPath = newSegments.join('/');
123
+
124
+ // Always navigate to explorer URL - let the route system handle state
125
+ goto(`/explorer/${folderName}/${fullPath}`);
126
+ }
127
+
128
+ /**
129
+ * Handle breadcrumb navigation
130
+ * @param {number} level - Level to navigate back to
131
+ */
132
+ function navigateToLevel(level) {
133
+ if (level === 0) {
134
+ // Navigate back to root explorer
135
+ goto('/explorer');
136
+ } else {
137
+ // Navigate to specific level
138
+ const currentSegments =
139
+ interactiveSegments.length > 0 ? interactiveSegments : pathSegments;
140
+ const newSegments = currentSegments.slice(0, level);
141
+ const explorerPath = newSegments.join('/');
142
+ goto(`/explorer/${folderName}/${explorerPath}`);
143
+ }
144
+ }
145
+
146
+ // Expose the navigate function to parent
147
+ if (getNavigateToLevelFunction) {
148
+ getNavigateToLevelFunction(navigateToLevel);
149
+ }
150
+ </script>
151
+
152
+ <div class="explorer-container">
153
+ <!-- Dynamic columns -->
154
+ <div class="navigation-columns">
155
+ {#each breadcrumbColumns as column, columnIndex}
156
+ <div class="column" data-column={`level-${column.level}`}>
157
+ <h2 class="type-heading-h2 mb-20up">{column.title}</h2>
158
+ <nav class="folder-list">
159
+ {#each column.items as item}
160
+ <button
161
+ class="folder-item"
162
+ class:active={item.isSelected}
163
+ class:endpoint={item.isEndpoint}
164
+ onclick={() =>
165
+ handleNavigation(column.level, item.name, item.isEndpoint)}
166
+ >
167
+ <div class="item-content">
168
+ <div class="item-icon">
169
+ {#if item.isEndpoint}
170
+ <svg
171
+ class="external-icon"
172
+ viewBox="0 0 16 16"
173
+ fill="currentColor"
174
+ aria-hidden="true"
175
+ >
176
+ <path d="M3.5 2A1.5 1.5 0 002 3.5v9A1.5 1.5 0 003.5 14h9a1.5 1.5 0 001.5-1.5V9.75a.75.75 0 00-1.5 0v2.75a.25.25 0 01-.25.25h-8.5a.25.25 0 01-.25-.25v-8.5a.25.25 0 01.25-.25H6.5a.75.75 0 000-1.5h-3z"/>
177
+ <path d="M15.25 1a.75.75 0 00-.75-.75h-4.5a.75.75 0 000 1.5h2.69l-6.22 6.22a.75.75 0 101.06 1.06L13.75 3.31v2.69a.75.75 0 001.5 0V1z"/>
178
+ </svg>
179
+ {:else}
180
+ <svg
181
+ class="folder-icon"
182
+ viewBox="0 0 16 16"
183
+ fill="currentColor"
184
+ aria-hidden="true"
185
+ >
186
+ <path d="M1.75 2A1.75 1.75 0 000 3.75v8.5C0 13.216.784 14 1.75 14h12.5A1.75 1.75 0 0016 12.25v-7.5A1.75 1.75 0 0014.25 3H7.5L6.25 1.75A.75.75 0 005.75 1.5h-4A1.75 1.75 0 000 3.25V3.75z"/>
187
+ </svg>
188
+ {/if}
189
+ </div>
190
+ <span class="item-name">{item.displayName}</span>
191
+ </div>
192
+ </button>
193
+ {/each}
194
+
195
+ {#if column.items.length === 0}
196
+ <div class="empty-state">
197
+ <p class="type-base-sm">No items found</p>
198
+ </div>
199
+ {/if}
200
+ </nav>
201
+ </div>
202
+ {/each}
203
+ </div>
204
+ </div>
205
+
206
+ <style>
207
+ .explorer-container {
208
+ padding: 20px;
209
+ }
210
+
211
+ .navigation-columns {
212
+ display: grid;
213
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
214
+ gap: 30px;
215
+ align-items: start;
216
+ }
217
+
218
+ .column {
219
+ min-height: 200px;
220
+ }
221
+
222
+ .folder-list {
223
+ display: flex;
224
+ flex-direction: column;
225
+ gap: 4px;
226
+ }
227
+
228
+ .folder-item {
229
+ display: block;
230
+ width: 100%;
231
+ padding: 12px 16px;
232
+ background: none;
233
+ border: none;
234
+ text-align: left;
235
+ cursor: pointer;
236
+ color: var(--color-surface-700);
237
+ transition: all 0.2s;
238
+ font-size: 14px;
239
+ line-height: 1.4;
240
+ }
241
+
242
+ .folder-item:hover {
243
+ background-color: var(--color-surface-100);
244
+ }
245
+
246
+ .folder-item.active {
247
+ background-color: var(--color-primary-100);
248
+ color: var(--color-primary-700);
249
+ }
250
+
251
+ .folder-item.endpoint:hover {
252
+ background-color: var(--color-primary-50);
253
+ color: var(--color-primary-600);
254
+ }
255
+
256
+ .item-content {
257
+ display: flex;
258
+ align-items: center;
259
+ gap: 8px;
260
+ }
261
+
262
+ .item-icon {
263
+ display: flex;
264
+ align-items: center;
265
+ width: 14px;
266
+ height: 14px;
267
+ flex-shrink: 0;
268
+ }
269
+
270
+ .item-name {
271
+ flex: 1;
272
+ }
273
+
274
+ .external-icon,
275
+ .folder-icon {
276
+ width: 14px;
277
+ height: 14px;
278
+ opacity: 0.6;
279
+ transition: opacity 0.2s;
280
+ }
281
+
282
+ .folder-item:hover .external-icon,
283
+ .folder-item:hover .folder-icon {
284
+ opacity: 0.8;
285
+ }
286
+
287
+ .folder-item.endpoint .external-icon {
288
+ color: var(--color-primary-600);
289
+ }
290
+
291
+ .folder-item .folder-icon {
292
+ color: var(--color-surface-500);
293
+ }
294
+
295
+ .empty-state {
296
+ padding: 20px;
297
+ text-align: center;
298
+ color: var(--color-surface-500);
299
+ }
300
+ </style>
@@ -0,0 +1,20 @@
1
+ export default Explorer;
2
+ type Explorer = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<{
5
+ navigationData: any;
6
+ currentPath: string;
7
+ getActiveSegments?: (segments: string[]) => void;
8
+ getNavigateToLevelFunction?: (fn: Function) => void;
9
+ rootName?: string;
10
+ folderName?: string;
11
+ }>): void;
12
+ };
13
+ declare const Explorer: import("svelte").Component<{
14
+ navigationData: any;
15
+ currentPath: string;
16
+ getActiveSegments?: (segments: string[]) => void;
17
+ getNavigateToLevelFunction?: (fn: Function) => void;
18
+ rootName?: string;
19
+ folderName?: string;
20
+ }, {}, "">;
@@ -0,0 +1,82 @@
1
+ <script>
2
+ import { enhance } from '$app/forms';
3
+
4
+ import { Panel } from '../../primitives.js';
5
+
6
+ /**
7
+ * @type {{
8
+ * scalingEnabled: boolean,
9
+ * onchange?: (enabled: boolean) => void,
10
+ * crumblePath?: import('svelte').Snippet
11
+ * }}
12
+ */
13
+ let { scalingEnabled = $bindable(), onchange, crumblePath } = $props();
14
+ </script>
15
+
16
+ <div class="examples-top-bar" data-component="top-bar">
17
+ <div class="container">
18
+ {#if crumblePath}
19
+ <div class="crumble-path">
20
+ {@render crumblePath()}
21
+ </div>
22
+ {/if}
23
+
24
+ <form
25
+ method="POST"
26
+ action="?/toggleScaling"
27
+ use:enhance={({ formData, cancel }) => {
28
+ const newValue = formData.get('scalingEnabled') === 'on';
29
+ scalingEnabled = newValue;
30
+ onchange?.(newValue);
31
+
32
+ return async ({ result }) => {
33
+ if (result.type === 'success') {
34
+ // Force page reload to apply scaling changes
35
+ window.location.reload();
36
+ }
37
+ };
38
+ }}
39
+ >
40
+ <label class="scaling-toggle">
41
+ <input
42
+ type="checkbox"
43
+ name="scalingEnabled"
44
+ bind:checked={scalingEnabled}
45
+ onchange={(e) => /** @type {HTMLInputElement} */ (e.target).form.requestSubmit()}
46
+ />
47
+ <span class="type-ui-sm">Enable Design Scaling</span>
48
+ </label>
49
+ </form>
50
+ </div>
51
+ </div>
52
+
53
+ <style src="./topbar.css">@reference '../../../../app.css';
54
+
55
+ [data-component="top-bar"] {
56
+ @apply bg-surface-100 border-surface-300 sticky top-0 z-10;
57
+ @apply p-8ht;
58
+
59
+ & .container {
60
+ @apply max-w-screen-xl mx-auto flex justify-between items-center;
61
+ }
62
+
63
+ & .scaling-toggle {
64
+ @apply flex items-center cursor-pointer;
65
+ @apply gap-8bt;
66
+
67
+ & input[type="checkbox"] {
68
+ @apply accent-primary-500;
69
+ }
70
+ }
71
+
72
+ & .crumble-path {
73
+ @apply flex items-center;
74
+ }
75
+ }
76
+
77
+ /* Dark mode support */
78
+ @media (prefers-color-scheme: dark) {
79
+ [data-component="top-bar"] {
80
+ @apply bg-surface-800 border-surface-600;
81
+ }
82
+ }</style>
@@ -0,0 +1,14 @@
1
+ export default TopBar;
2
+ type TopBar = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<{
5
+ scalingEnabled: boolean;
6
+ onchange?: (enabled: boolean) => void;
7
+ crumblePath?: Snippet<[]>;
8
+ }>): void;
9
+ };
10
+ declare const TopBar: import("svelte").Component<{
11
+ scalingEnabled: boolean;
12
+ onchange?: (enabled: boolean) => void;
13
+ crumblePath?: import("svelte").Snippet;
14
+ }, {}, "scalingEnabled">;
@@ -0,0 +1,2 @@
1
+ export { default as Explorer } from "./Explorer.svelte";
2
+ export { default as TopBar } from "./TopBar.svelte";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Dev explorer components
3
+ * @fileoverview Reusable components for navigating nested folder
4
+ * structures with dynamic routing support
5
+ */
6
+
7
+ export { default as Explorer } from './Explorer.svelte';
8
+ export { default as TopBar } from './TopBar.svelte';
@@ -0,0 +1,30 @@
1
+ @reference '../../../../app.css';
2
+
3
+ [data-component="top-bar"] {
4
+ @apply bg-surface-100 border-surface-300 sticky top-0 z-10;
5
+ @apply p-8ht;
6
+
7
+ & .container {
8
+ @apply max-w-screen-xl mx-auto flex justify-between items-center;
9
+ }
10
+
11
+ & .scaling-toggle {
12
+ @apply flex items-center cursor-pointer;
13
+ @apply gap-8bt;
14
+
15
+ & input[type="checkbox"] {
16
+ @apply accent-primary-500;
17
+ }
18
+ }
19
+
20
+ & .crumble-path {
21
+ @apply flex items-center;
22
+ }
23
+ }
24
+
25
+ /* Dark mode support */
26
+ @media (prefers-color-scheme: dark) {
27
+ [data-component="top-bar"] {
28
+ @apply bg-surface-800 border-surface-600;
29
+ }
30
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-core",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"