lapikit 0.0.0-insiders.bd609af → 0.0.0-insiders.c3399e0

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.
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { promises as fs } from 'fs';
3
3
  import path from 'path';
4
+ import { terminal } from './helper.js';
4
5
  import presets from './presets.js';
5
6
 
6
7
  async function findReferenceFile(projectPath) {
@@ -9,7 +10,8 @@ async function findReferenceFile(projectPath) {
9
10
  try {
10
11
  await fs.access(routesPath);
11
12
  } catch {
12
- throw new Error('Lapikit cannot find the routes/ directory.');
13
+ terminal('error', `Lapikit cannot find the routes/ directory.`);
14
+ // throw new Error('Lapikit cannot find the routes/ directory.');
13
15
  }
14
16
 
15
17
  const layoutFile = path.join(routesPath, '+layout.svelte');
@@ -65,7 +67,7 @@ async function addImportToReferenceFile(targetFile, referenceFile) {
65
67
  const importStatement = `import "${relativePath.startsWith('.') ? relativePath : './' + relativePath}";\n`;
66
68
 
67
69
  if (content.includes(`import "${relativePath}"`)) {
68
- console.log(`import has already exist ${referenceFile}`);
70
+ terminal('info', `Import statement already exists in ${referenceFile}`);
69
71
  return;
70
72
  }
71
73
 
@@ -103,9 +105,9 @@ async function addImportToReferenceFile(targetFile, referenceFile) {
103
105
  const newContent = lines.join('\n');
104
106
 
105
107
  await fs.writeFile(referenceFile, newContent);
106
- console.log(`Import has added on ${referenceFile}`);
108
+ terminal('info', `Import has been added to ${referenceFile}`);
107
109
  } catch (error) {
108
- console.error(`Error adding import: ${error.message}`);
110
+ terminal('error', `Error adding import: ${error.message}`);
109
111
  throw error;
110
112
  }
111
113
  }
@@ -131,14 +133,16 @@ async function findViteConfigFile(projectPath, typescript) {
131
133
  }
132
134
  }
133
135
 
134
- async function addLapikitToViteConfig(viteConfigFile) {
136
+ async function addLapikitToViteConfig(viteConfigFile, pathConfig, typescript) {
135
137
  try {
136
138
  const content = await fs.readFile(viteConfigFile, 'utf-8');
137
139
  const lapikitImport = `import { lapikit } from 'lapikit/vite';`;
140
+ const configPath = `${pathConfig}/lapikit.${typescript ? 'ts' : 'js'}`;
141
+ const lapikitPlugin = `lapikit({ config: '${configPath}' })`;
138
142
 
139
143
  // Check if lapikit import already exists
140
144
  if (content.includes(lapikitImport) || content.includes(`from 'lapikit/vite'`)) {
141
- console.log(`Lapikit import already exists in ${viteConfigFile}`);
145
+ terminal('info', `Lapikit import already exists in ${viteConfigFile}`);
142
146
  return;
143
147
  }
144
148
 
@@ -181,10 +185,10 @@ async function addLapikitToViteConfig(viteConfigFile) {
181
185
  const pluginMatch = line.match(/plugins:\s*\[(.*)\]/);
182
186
  if (pluginMatch) {
183
187
  const pluginsContent = pluginMatch[1];
184
- if (!pluginsContent.includes('lapikit()')) {
188
+ if (!pluginsContent.includes('lapikit')) {
185
189
  const newPluginsContent = pluginsContent.replace(
186
190
  /sveltekit\(\)/,
187
- 'sveltekit(), lapikit()'
191
+ `sveltekit(), ${lapikitPlugin}`
188
192
  );
189
193
  lines[i] = line.replace(pluginsContent, newPluginsContent);
190
194
  pluginAdded = true;
@@ -198,24 +202,24 @@ async function addLapikitToViteConfig(viteConfigFile) {
198
202
  const pluginLine = lines[j].trim();
199
203
 
200
204
  if (pluginLine.includes('sveltekit()') && !pluginAdded) {
201
- // Check if lapikit() is not already present
205
+ // Check if lapikit is not already present
202
206
  let hasLapikit = false;
203
207
  for (let k = i; k < lines.length && !lines[k].includes(']'); k++) {
204
- if (lines[k].includes('lapikit()')) {
208
+ if (lines[k].includes('lapikit')) {
205
209
  hasLapikit = true;
206
210
  break;
207
211
  }
208
212
  }
209
213
 
210
214
  if (!hasLapikit) {
211
- // Add lapikit() after sveltekit()
215
+ // Add lapikit after sveltekit()
212
216
  if (pluginLine.includes(',')) {
213
- lines[j] = lines[j].replace('sveltekit()', 'sveltekit(), lapikit()');
217
+ lines[j] = lines[j].replace('sveltekit()', `sveltekit(), ${lapikitPlugin}`);
214
218
  } else {
215
219
  lines[j] = lines[j].replace('sveltekit()', 'sveltekit(),');
216
- // Insert lapikit() on the next line with proper indentation
220
+ // Insert lapikit on the next line with proper indentation
217
221
  const indentation = lines[j].match(/^\s*/)[0];
218
- lines.splice(j + 1, 0, `${indentation}lapikit()`);
222
+ lines.splice(j + 1, 0, `${indentation}${lapikitPlugin}`);
219
223
  }
220
224
  pluginAdded = true;
221
225
  }
@@ -231,21 +235,20 @@ async function addLapikitToViteConfig(viteConfigFile) {
231
235
  }
232
236
 
233
237
  if (!pluginAdded) {
234
- console.warn('Could not find sveltekit() in plugins array to add lapikit() after it');
238
+ terminal('warn', `Could not find sveltekit() in plugins array to add lapikit() after it`);
235
239
  }
236
240
 
237
241
  const newContent = lines.join('\n');
238
242
  await fs.writeFile(viteConfigFile, newContent);
239
- console.log(`Lapikit import and plugin added to ${viteConfigFile}`);
243
+ terminal('info', `Lapikit import and plugin added to ${viteConfigFile}`);
240
244
  } catch (error) {
241
- console.error(`Error adding lapikit to vite config: ${error.message}`);
245
+ terminal('error', `Error adding lapikit to vite config: ${error.message}`);
242
246
  throw error;
243
247
  }
244
248
  }
245
249
 
246
250
  export async function initConfiguration(options) {
247
- console.log('initConfiguration called with:', options);
248
- const { typescript, pathConfig, formatCSS } = options;
251
+ const { typescript, pathConfig, formatCSS, pathCSS } = options;
249
252
  const ext = typescript ? 'ts' : 'js';
250
253
  const targetDir = path.resolve(process.cwd(), pathConfig);
251
254
  const targetFile = path.join(targetDir, `lapikit.${ext}`);
@@ -253,30 +256,32 @@ export async function initConfiguration(options) {
253
256
  await fs.mkdir(targetDir, { recursive: true });
254
257
 
255
258
  let fileCreated = false;
259
+
260
+ // Create Lapikit config
256
261
  try {
257
- console.log(`Trying to access ${targetFile}`);
258
262
  await fs.access(targetFile);
259
- console.log(`File ${targetFile} already exists.`);
263
+ terminal('info', `File ${targetFile} already exists.`);
260
264
  } catch {
261
- console.log(`Creating file: ${targetFile}`);
265
+ terminal('info', `Creating file: ${targetFile}`);
262
266
  const content = presets({
263
- classic: formatCSS === 'global'
267
+ adapterCSS: formatCSS
264
268
  });
265
269
  await fs.writeFile(targetFile, content);
266
- console.log(`File created : ${targetFile}`);
270
+ terminal('info', `File created: ${targetFile}`);
267
271
  fileCreated = true;
268
272
  }
269
273
 
274
+ // Add Import Lapikit plugin
270
275
  try {
271
276
  const referenceFile = await findReferenceFile(process.cwd());
272
277
  await addImportToReferenceFile(targetFile, referenceFile);
273
278
  } catch (error) {
274
- console.error(`Error: ${error.message}`);
275
- // If the file was just created and we can't add the import, delete it
279
+ terminal('error', `Error adding import: ${error.message}`);
280
+
276
281
  if (fileCreated) {
277
282
  try {
278
283
  await fs.unlink(targetFile);
279
- console.log(`File ${targetFile} deleted due to error.`);
284
+ terminal('info', `File ${targetFile} deleted due to error.`);
280
285
  } catch {
281
286
  // Ignore deletion error
282
287
  }
@@ -284,12 +289,16 @@ export async function initConfiguration(options) {
284
289
  throw error;
285
290
  }
286
291
 
292
+ // Add Import Lapikit css
293
+ if (formatCSS !== 'css') {
294
+ console.log('need custom import (Preview)', pathCSS);
295
+ }
287
296
  // Add lapikit to vite.config file
288
297
  try {
289
298
  const viteConfigFile = await findViteConfigFile(process.cwd(), typescript);
290
- await addLapikitToViteConfig(viteConfigFile);
299
+ await addLapikitToViteConfig(viteConfigFile, pathConfig, typescript);
291
300
  } catch (error) {
292
- console.warn(`Warning: Could not update vite.config file: ${error.message}`);
293
- // This is not a critical error, so we don't throw it
301
+ terminal('warn', `Warning: Could not update vite.config file: ${error.message}`);
302
+ terminal('error', `Error adding lapikit to vite config: ${error.message}`);
294
303
  }
295
304
  }
package/bin/index.js CHANGED
@@ -30,12 +30,12 @@ async function run() {
30
30
 
31
31
  run()
32
32
  .then(() => {
33
- console.log('Website: https://lapikit.dev');
34
- console.log('Github: https://github.com/nycolaide/lapikit');
35
- console.log('Support the developement: https://buymeacoffee.com/nycolaide');
33
+ terminal('none', `\n\n\n\nWebsite: https://lapikit.dev`);
34
+ terminal('none', `Github: https://github.com/nycolaide/lapikit`);
35
+ terminal('none', `Support the developement: https://buymeacoffee.com/nycolaide`);
36
36
  process.exit(0);
37
37
  })
38
38
  .catch((error) => {
39
- console.error(`\n${red('')} ${error}\n`);
39
+ terminal('error', `Error: ${error}`);
40
40
  process.exit(1);
41
41
  });
package/bin/presets.js CHANGED
@@ -1,21 +1,24 @@
1
- function presets({ classic }) {
1
+ function presets({ adapterCSS }) {
2
2
  let content = '';
3
3
 
4
4
  content += `/**\n`;
5
- content += `\t* Lapikit\n`;
6
- content += `\t* Library documentation: https://lapikit.dev\n`;
5
+ content += ` * Lapikit\n`;
6
+ content += ` * Library documentation: https://lapikit.dev\n`;
7
7
  content += ` */\n\n`;
8
8
 
9
- if (classic) {
10
- content += `// Classic\n`;
9
+ if (adapterCSS === 'css') {
10
+ content += `// Styles\n`;
11
+ content += `import 'lapikit/styles';\n`;
11
12
  content += `import 'lapikit/css';\n\n`;
12
13
  }
13
14
 
14
15
  content += `// Composables\n`;
15
- content += `import { helloWorld } from 'lapikit';\n\n`;
16
+ content += `import createLapikit from 'lapikit';\n\n`;
16
17
 
17
18
  content += `// https://lapikit.dev/docs/getting-started\n`;
18
- content += `export default helloWorld();`;
19
+ content += `export default createLapikit({\n`;
20
+ content += `\tadapterCSS: "${adapterCSS}",\n`;
21
+ content += `\n});`;
19
22
 
20
23
  return content;
21
24
  }
package/bin/prompts.js CHANGED
@@ -1,18 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import prompts from 'prompts';
3
+ import { terminal } from './helper.js';
3
4
 
4
5
  export async function initPrompts() {
5
6
  const { confirm } = await prompts({
6
7
  type: 'toggle',
7
8
  name: 'confirm',
8
- message: 'Start install Lapikit on your app?',
9
+ message: 'Launch install Lapikit on your project?',
9
10
  initial: true,
10
11
  active: 'Yes',
11
12
  inactive: 'No'
12
13
  });
13
14
 
14
15
  if (!confirm) {
15
- console.log(' Installation canceled. See you soon.');
16
+ terminal('warn', `installation canceled.`);
16
17
  process.exit(0);
17
18
  }
18
19
  // temps with legacy and new process install
@@ -70,7 +71,7 @@ export async function initPrompts() {
70
71
  name: 'formatCSS',
71
72
  message: 'What is your CSS format used on your app?',
72
73
  choices: [
73
- { title: 'Basic (classic import)', value: 'global' },
74
+ { title: 'Basic (classic import)', value: 'css' },
74
75
  {
75
76
  title: 'TailwindCSS (v4)',
76
77
  value: 'tailwind-v4'
@@ -82,7 +83,7 @@ export async function initPrompts() {
82
83
  ]
83
84
  },
84
85
  {
85
- type: (prev) => (prev !== 'global' ? 'text' : null),
86
+ type: (prev) => (prev !== 'css' ? 'text' : null),
86
87
  name: 'pathCSS',
87
88
  message: 'Where would you like to import the lapikit CSS files?',
88
89
  initial: 'src/app.css',
@@ -91,8 +92,6 @@ export async function initPrompts() {
91
92
  }
92
93
  ]);
93
94
 
94
- console.log('response config', settings);
95
-
96
95
  return {
97
96
  ...settings,
98
97
  env: 'experimental'
File without changes
@@ -4,7 +4,8 @@
4
4
  colorSchemeSystem,
5
5
  modalOpen,
6
6
  setOpenModal,
7
- updateThemeStore
7
+ useColorScheme,
8
+ useTheme
8
9
  } from '../../stores/index.js';
9
10
  import type { Snippet } from 'svelte';
10
11
  let { children }: { children: Snippet } = $props();
@@ -26,8 +27,12 @@
26
27
  });
27
28
 
28
29
  // local
29
- const local = localStorage.getItem('@lapikit/theme');
30
- if (local !== null) updateThemeStore(local as 'dark' | 'light' | 'system');
30
+ const localColorScheme = localStorage.getItem('@lapikit/color-scheme');
31
+ const localTheme = localStorage.getItem('@lapikit/theme');
32
+
33
+ // apply local settings
34
+ if (localColorScheme !== null) useColorScheme(localColorScheme as 'dark' | 'light' | 'system');
35
+ if (localTheme !== null) useTheme(localTheme as string);
31
36
  });
32
37
  </script>
33
38
 
@@ -20,7 +20,7 @@
20
20
  text-decoration: none;
21
21
  }
22
22
 
23
- .kit-chip:not(div):not(span) {
23
+ .kit-chip:not(div):not(span):not(.kit-chip--readonly) {
24
24
  cursor: pointer;
25
25
  }
26
26
 
@@ -49,13 +49,13 @@
49
49
  pointer-events: none;
50
50
  border-radius: inherit;
51
51
  }
52
- .kit-chip:not(div):not(span):hover::after {
52
+ .kit-chip:not(div):not(span):not(.kit-chip--readonly):hover::after {
53
53
  opacity: 0.08;
54
54
  }
55
- .kit-chip:not(div):not(span):active::after {
55
+ .kit-chip:not(div):not(span):not(.kit-chip--readonly):active::after {
56
56
  opacity: 0.12;
57
57
  }
58
- .kit-chip:not(div):not(span):focus-visible::after {
58
+ .kit-chip:not(div):not(span):not(.kit-chip--readonly):focus-visible::after {
59
59
  opacity: 0.12;
60
60
  }
61
61
 
@@ -37,6 +37,7 @@
37
37
  rounded,
38
38
  closable,
39
39
  noRipple,
40
+ readonly = false,
40
41
  ...rest
41
42
  }: ChipProps = $props();
42
43
 
@@ -44,7 +45,7 @@
44
45
 
45
46
  $effect(() => {
46
47
  const refProps = { ...rest };
47
- if (refProps?.onclick) is = 'button';
48
+ if (refProps?.onclick && !readonly) is = 'button';
48
49
  });
49
50
  </script>
50
51
 
@@ -68,6 +69,7 @@
68
69
  disabled && 'kit-chip--disabled',
69
70
  active && 'kit-chip--active',
70
71
  loading && 'kit-chip--loading',
72
+ readonly && 'kit-chip--readonly',
71
73
  rest.class
72
74
  ]}
73
75
  tabindex={href && disabled ? -1 : 0}
@@ -77,7 +79,7 @@
77
79
  type={href ? undefined : type}
78
80
  use:ripple={{
79
81
  component: 'chip',
80
- disabled: noRipple || disabled || is === 'div' || is === 'span'
82
+ disabled: noRipple || readonly || disabled || is === 'div' || is === 'span'
81
83
  }}
82
84
  style:--base={assets.color(background)}
83
85
  style:--on={assets.color(color)}
@@ -109,7 +111,7 @@
109
111
  </div>
110
112
  {/if}
111
113
 
112
- {#if closable}
114
+ {#if closable && !readonly}
113
115
  <button
114
116
  class="kit-chip--close"
115
117
  type="button"
@@ -28,4 +28,5 @@ export interface ChipProps extends Component {
28
28
  label?: string;
29
29
  closable?: boolean;
30
30
  noRipple?: boolean;
31
+ readonly?: boolean;
31
32
  }
@@ -60,7 +60,9 @@
60
60
  }
61
61
 
62
62
  .kit-dialog[breakpoint]kit-dialog--position-center {
63
- margin: auto;
63
+ /* margin: auto; */
64
+ margin-top: auto;
65
+ margin-bottom: auto;
64
66
  }
65
67
 
66
68
  .kit-dialog[breakpoint]kit-dialog--size-xs {
@@ -49,7 +49,6 @@
49
49
  max-height: calc(100% - 3rem);
50
50
  height: fit-content;
51
51
  margin: 0 auto;
52
- top: 50%;
53
52
  left: 50%;
54
53
  bottom: initial;
55
54
  translate: var(--modal-translate-x) var(--modal-translate-y);
@@ -60,7 +59,6 @@
60
59
  max-height: calc(100% - 3rem);
61
60
  height: fit-content;
62
61
  margin: 0 auto;
63
- top: 50%;
64
62
  left: 50%;
65
63
  bottom: initial;
66
64
  translate: var(--modal-translate-x) var(--modal-translate-y);
@@ -71,7 +69,6 @@
71
69
  max-height: calc(100% - 3rem);
72
70
  height: fit-content;
73
71
  margin: 0 auto;
74
- top: 50%;
75
72
  left: 50%;
76
73
  bottom: initial;
77
74
  translate: var(--modal-translate-x) var(--modal-translate-y);
@@ -82,7 +79,6 @@
82
79
  max-height: calc(100% - 3rem);
83
80
  height: fit-content;
84
81
  margin: 0 auto;
85
- top: 50%;
86
82
  left: 50%;
87
83
  bottom: initial;
88
84
  translate: var(--modal-translate-x) var(--modal-translate-y);
@@ -93,7 +89,6 @@
93
89
  max-height: calc(100% - 3rem);
94
90
  height: fit-content;
95
91
  margin: 0 auto;
96
- top: 50%;
97
92
  left: 50%;
98
93
  bottom: initial;
99
94
  translate: var(--modal-translate-x) var(--modal-translate-y);
@@ -130,15 +125,21 @@
130
125
  /* position */
131
126
  .kit-modal [breakpoint]kit-modal-container--position-bottom {
132
127
  --modal-translate-y: 0;
133
- bottom: 0;
128
+ margin: auto;
134
129
  top: initial;
130
+ bottom: 0;
135
131
  }
136
132
 
137
133
  .kit-modal [breakpoint]kit-modal-container--position-top {
138
134
  --modal-translate-y: 0;
135
+ margin: auto;
139
136
  top: 0;
137
+ bottom: initial;
140
138
  }
141
139
 
142
140
  .kit-modal [breakpoint]kit-modal-container--position-center {
141
+ --modal-translate-y: -50%;
143
142
  margin: auto;
143
+ top: 50%;
144
+ bottom: initial;
144
145
  }
package/dist/index.d.ts CHANGED
@@ -1 +1,27 @@
1
- export declare function helloWorld(): void;
1
+ interface Lapikit {
2
+ adapterCSS: string;
3
+ breakpoints: {
4
+ devices: {
5
+ [key: string]: string;
6
+ };
7
+ thresholds: {
8
+ [key: string]: number | string;
9
+ };
10
+ };
11
+ theme: {
12
+ defaultTheme: string;
13
+ themes: {
14
+ [key: string]: {
15
+ dark: boolean;
16
+ colors: {
17
+ [key: string]: string;
18
+ };
19
+ variables: {
20
+ [key: string]: string;
21
+ };
22
+ };
23
+ };
24
+ };
25
+ }
26
+ declare function createLapikit(lapikit: Lapikit): void;
27
+ export default createLapikit;
package/dist/index.js CHANGED
@@ -1,4 +1,28 @@
1
- // Reexport your entry components here
2
- export function helloWorld() {
3
- console.log('Hello world, this is lapikit!');
1
+ import { deepMerge } from './internal/deepMerge.js';
2
+ import { breakpoints } from './stores/breakpoints.js';
3
+ import { get } from 'svelte/store';
4
+ import { valueToPx } from './utils/convert.js';
5
+ import { devices } from './stores/devices.js';
6
+ function createLapikit(lapikit) {
7
+ console.log('Creating a new Lapikit instance...');
8
+ console.log('Options loaded:', lapikit);
9
+ if (lapikit?.breakpoints?.thresholds) {
10
+ const currentBreakpoints = get(breakpoints);
11
+ const breakpointMerged = deepMerge(currentBreakpoints, lapikit.breakpoints.thresholds);
12
+ const formattedBreakpoints = Object.fromEntries(Object.entries(breakpointMerged).map(([key, value]) => [key, valueToPx(value)]));
13
+ breakpoints.set(formattedBreakpoints);
14
+ console.log('Breakpoints found:', formattedBreakpoints);
15
+ }
16
+ if (lapikit?.breakpoints?.devices) {
17
+ const currentDevices = get(devices);
18
+ const currentBreakpoints = get(breakpoints);
19
+ const deviceMerged = deepMerge(currentDevices, lapikit.breakpoints.devices);
20
+ const formattedDevices = Object.fromEntries(Object.entries(deviceMerged).map(([key, deviceKey]) => {
21
+ const breakpointValue = currentBreakpoints[deviceKey];
22
+ return [key, valueToPx(breakpointValue)];
23
+ }));
24
+ devices.set(formattedDevices);
25
+ console.log('Devices found:', formattedDevices);
26
+ }
4
27
  }
28
+ export default createLapikit;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Recursively merges two objects together.
3
+ * Properties from the source object override those from the target object.
4
+ * Nested objects are merged recursively.
5
+ *
6
+ * @param target - The base object
7
+ * @param source - The source object to merge (can be null or undefined)
8
+ * @returns A new object containing the merge of both objects
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const obj1 = { primary: { light: 'pink', medium: 'purple' } };
13
+ * const obj2 = { primary: { dark: 'red' } };
14
+ * const result = deepMerge(obj1, obj2);
15
+ * // Result: { primary: { light: 'pink', medium: 'purple', dark: 'red' } }
16
+ *
17
+ * // Works with null/undefined source
18
+ * const result2 = deepMerge(obj1, null);
19
+ * // Result: { primary: { light: 'pink', medium: 'purple' } }
20
+ * ```
21
+ */
22
+ export declare function deepMerge<T extends Record<string, unknown>, U extends Record<string, unknown>>(target: T, source: U | null | undefined): T & U;
23
+ /**
24
+ * Merges multiple objects together recursively.
25
+ *
26
+ * @param objects - The objects to merge (null and undefined values are ignored)
27
+ * @returns A new object containing the merge of all objects
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const result = deepMergeMultiple(
32
+ * { primary: { light: 'pink' } },
33
+ * null,
34
+ * { primary: { dark: 'red' } },
35
+ * undefined,
36
+ * { secondary: { light: 'blue' } }
37
+ * );
38
+ * // Result: {
39
+ * // primary: { light: 'pink', dark: 'red' },
40
+ * // secondary: { light: 'blue' }
41
+ * // }
42
+ * ```
43
+ */
44
+ export declare function deepMergeMultiple(...objects: (Record<string, unknown> | null | undefined)[]): Record<string, unknown>;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Checks if a value is a plain object (object literal)
3
+ */
4
+ function isPlainObject(value) {
5
+ return (value !== null &&
6
+ typeof value === 'object' &&
7
+ Object.prototype.toString.call(value) === '[object Object]');
8
+ }
9
+ /**
10
+ * Recursively merges two objects together.
11
+ * Properties from the source object override those from the target object.
12
+ * Nested objects are merged recursively.
13
+ *
14
+ * @param target - The base object
15
+ * @param source - The source object to merge (can be null or undefined)
16
+ * @returns A new object containing the merge of both objects
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const obj1 = { primary: { light: 'pink', medium: 'purple' } };
21
+ * const obj2 = { primary: { dark: 'red' } };
22
+ * const result = deepMerge(obj1, obj2);
23
+ * // Result: { primary: { light: 'pink', medium: 'purple', dark: 'red' } }
24
+ *
25
+ * // Works with null/undefined source
26
+ * const result2 = deepMerge(obj1, null);
27
+ * // Result: { primary: { light: 'pink', medium: 'purple' } }
28
+ * ```
29
+ */
30
+ export function deepMerge(target, source) {
31
+ // If source is null or undefined, return a copy of target
32
+ if (source == null) {
33
+ return { ...target };
34
+ }
35
+ // Create a copy of the target object to avoid mutations
36
+ const result = { ...target };
37
+ for (const key in source) {
38
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
39
+ const sourceValue = source[key];
40
+ const targetValue = result[key];
41
+ // If both values are plain objects, merge them recursively
42
+ if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
43
+ result[key] = deepMerge(targetValue, sourceValue);
44
+ }
45
+ else {
46
+ // Otherwise, the source value overrides the target value
47
+ result[key] = sourceValue;
48
+ }
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+ /**
54
+ * Merges multiple objects together recursively.
55
+ *
56
+ * @param objects - The objects to merge (null and undefined values are ignored)
57
+ * @returns A new object containing the merge of all objects
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const result = deepMergeMultiple(
62
+ * { primary: { light: 'pink' } },
63
+ * null,
64
+ * { primary: { dark: 'red' } },
65
+ * undefined,
66
+ * { secondary: { light: 'blue' } }
67
+ * );
68
+ * // Result: {
69
+ * // primary: { light: 'pink', dark: 'red' },
70
+ * // secondary: { light: 'blue' }
71
+ * // }
72
+ * ```
73
+ */
74
+ export function deepMergeMultiple(...objects) {
75
+ return objects
76
+ .filter((obj) => obj != null)
77
+ .reduce((acc, obj) => {
78
+ return deepMerge(acc, obj);
79
+ }, {});
80
+ }
@@ -0,0 +1 @@
1
+ export declare function css(configuration: any): Promise<void>;
@@ -0,0 +1,76 @@
1
+ import { deepMerge } from '../internal/deepMerge.js';
2
+ import { preset } from './preset-v2.js';
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname } from 'path';
5
+ import fsPromises from 'fs/promises';
6
+ import path from 'path';
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ export async function css(configuration) {
11
+ console.log('VALUE configuration', configuration);
12
+ console.log('configuration?.theme?.themes', configuration?.theme?.themes);
13
+ // states
14
+ const defaultTheme = configuration?.theme?.defaultTheme || preset.theme.defaultTheme;
15
+ const themesMerged = deepMerge(preset.theme.themes, configuration?.theme?.themes || {});
16
+ let response = '';
17
+ console.log('VALUE themesMerged', themesMerged);
18
+ for (const [name, values] of Object.entries(themesMerged)) {
19
+ let css = defaultTheme === name ? `:root,\n.${name} {\n` : `.${name} {\n`;
20
+ // ref
21
+ const ref = values?.dark ? preset.theme.themes.dark : preset.theme.themes.light;
22
+ // colors
23
+ css += ` color-scheme: ${values?.dark ? 'dark' : 'light'};\n`;
24
+ for (const [varName, varValue] of Object.entries(deepMerge(ref.colors, values?.colors) || {})) {
25
+ css += ` --system-${varName}: ${varValue};\n`;
26
+ }
27
+ // console.log('VALUE', values, deepMerge(values?.variables, ref.variables));
28
+ // variables
29
+ for (const [name, varValue] of Object.entries(deepMerge(ref.variables, values?.variables) || {})) {
30
+ css += ` --kit-${name}: ${varValue};\n`;
31
+ }
32
+ css += '}\n';
33
+ // console.log(`Themes colors (${name}):`, css);
34
+ response += css;
35
+ }
36
+ // console.log('All themes CSS:', response);
37
+ //typography
38
+ // states
39
+ const defaultTypography = configuration?.typography?.defaultTypography || preset.typography.defaultTypography;
40
+ for (const [name, values] of Object.entries(deepMerge(preset.typography.fonts, configuration?.typography?.fonts || {}))) {
41
+ let css = '';
42
+ css += defaultTypography === name ? `:root {\n` : `.${name} {\n`;
43
+ // fonts
44
+ for (const [fontName, fontValue] of Object.entries(values || {})) {
45
+ css += ` --kit-font-${fontName}: ${parser(fontValue)};\n`;
46
+ }
47
+ css += '}\n';
48
+ response += css;
49
+ }
50
+ //styles
51
+ response += `:root {\n`;
52
+ for (const [name, values] of Object.entries(deepMerge(preset.styles, configuration?.styles || {}))) {
53
+ let css = '';
54
+ for (const [styleName, styleValue] of Object.entries(values || {})) {
55
+ console.log('VALUE', styleName, styleValue, typeof styleValue);
56
+ if (typeof styleValue === 'object') {
57
+ for (const [subStyleName, subStyleValue] of Object.entries(styleValue)) {
58
+ css += ` --prism-${styleName}-${subStyleName}: ${parser(subStyleValue)};\n`;
59
+ }
60
+ }
61
+ else {
62
+ css += ` --prism-${styleName}: ${parser(styleValue)};\n`;
63
+ }
64
+ }
65
+ response += css;
66
+ }
67
+ response += '}\n';
68
+ fsPromises.writeFile(path.resolve(__dirname, '../colors.css'), response);
69
+ }
70
+ const parser = (value) => {
71
+ if (typeof value === 'number')
72
+ return `${value}px`;
73
+ if (Array.isArray(value))
74
+ return value.join(', ');
75
+ return value;
76
+ };
@@ -0,0 +1,108 @@
1
+ export declare const preset: {
2
+ breakpoints: {
3
+ devices: {
4
+ desktop: number;
5
+ tablet: number;
6
+ mobile: number;
7
+ };
8
+ thresholds: {
9
+ base: number;
10
+ xs: number;
11
+ sm: number;
12
+ md: number;
13
+ lg: number;
14
+ xl: number;
15
+ '2xl': number;
16
+ '3xl': number;
17
+ };
18
+ };
19
+ theme: {
20
+ defaultTheme: string;
21
+ themes: {
22
+ light: {
23
+ dark: boolean;
24
+ colors: {
25
+ blue: string;
26
+ green: string;
27
+ red: string;
28
+ yellow: string;
29
+ orange: string;
30
+ purple: string;
31
+ pink: string;
32
+ indigo: string;
33
+ cyan: string;
34
+ gray: string;
35
+ 'gray-2': string;
36
+ 'gray-3': string;
37
+ 'gray-4': string;
38
+ 'gray-5': string;
39
+ 'gray-6': string;
40
+ background: string;
41
+ 'secondary-background': string;
42
+ 'tertiary-background': string;
43
+ label: string;
44
+ 'secondary-label': string;
45
+ };
46
+ variables: {
47
+ info: string;
48
+ success: string;
49
+ error: string;
50
+ warning: string;
51
+ };
52
+ };
53
+ dark: {
54
+ dark: boolean;
55
+ colors: {
56
+ blue: string;
57
+ green: string;
58
+ red: string;
59
+ yellow: string;
60
+ orange: string;
61
+ purple: string;
62
+ pink: string;
63
+ indigo: string;
64
+ cyan: string;
65
+ gray: string;
66
+ 'gray-2': string;
67
+ 'gray-3': string;
68
+ 'gray-4': string;
69
+ 'gray-5': string;
70
+ 'gray-6': string;
71
+ background: string;
72
+ 'secondary-background': string;
73
+ 'tertiary-background': string;
74
+ label: string;
75
+ 'secondary-label': string;
76
+ };
77
+ variables: {
78
+ info: string;
79
+ success: string;
80
+ error: string;
81
+ warning: string;
82
+ };
83
+ };
84
+ };
85
+ };
86
+ typography: {
87
+ defaultTypography: string;
88
+ fonts: {
89
+ default: {
90
+ sans: string[];
91
+ mono: string[];
92
+ serif: string[];
93
+ };
94
+ };
95
+ };
96
+ styles: {
97
+ spacing: string;
98
+ shape: {
99
+ sm: string;
100
+ md: string;
101
+ lg: string;
102
+ xl: string;
103
+ '2xl': string;
104
+ '3xl': string;
105
+ full: string;
106
+ };
107
+ };
108
+ };
@@ -0,0 +1,126 @@
1
+ const variables = {
2
+ info: 'var(--system-blue)',
3
+ success: 'var(--system-green)',
4
+ error: 'var(--system-red)',
5
+ warning: 'var(--system-yellow)'
6
+ };
7
+ export const preset = {
8
+ breakpoints: {
9
+ devices: {
10
+ desktop: 1024, //64rem (lg)
11
+ tablet: 768, //48rem (md)
12
+ mobile: 375 //28rem (sm)
13
+ },
14
+ thresholds: {
15
+ base: 0, // 0px
16
+ xs: 448, //28rem
17
+ sm: 640, //40rem
18
+ md: 768, //48rem
19
+ lg: 1024, //64rem
20
+ xl: 1280, //80rem
21
+ '2xl': 1536, //96rem
22
+ '3xl': 1792 //112rem
23
+ }
24
+ },
25
+ theme: {
26
+ defaultTheme: 'light',
27
+ themes: {
28
+ light: {
29
+ dark: false,
30
+ colors: {
31
+ blue: '#007AFF',
32
+ green: '#34C759',
33
+ red: '#FF3B30',
34
+ yellow: '#FFCC00',
35
+ orange: '#FF9500',
36
+ purple: '#AF52DE',
37
+ pink: '#FF2D55',
38
+ indigo: '#5856D6',
39
+ cyan: '#5AC8FA',
40
+ gray: '#8E8E93',
41
+ 'gray-2': '#AEAEB2',
42
+ 'gray-3': '#C7C7CC',
43
+ 'gray-4': '#D1D1D6',
44
+ 'gray-5': '#E5E5EA',
45
+ 'gray-6': '#F2F2F7',
46
+ background: '#FFFFFF',
47
+ 'secondary-background': '#F2F2F7',
48
+ 'tertiary-background': '#EFEFF4',
49
+ label: '#000000',
50
+ 'secondary-label': 'rgba(60,60,67,0.6)'
51
+ },
52
+ variables: variables
53
+ },
54
+ dark: {
55
+ dark: true,
56
+ colors: {
57
+ blue: '#0A84FF',
58
+ green: '#30D158',
59
+ red: '#FF453A',
60
+ yellow: '#FFD60A',
61
+ orange: '#FF9F0A',
62
+ purple: '#BF5AF2',
63
+ pink: '#FF375F',
64
+ indigo: '#5E5CE6',
65
+ cyan: '#64D2FF',
66
+ gray: '#8E8E93',
67
+ 'gray-2': '#636366',
68
+ 'gray-3': '#48484A',
69
+ 'gray-4': '#3A3A3C',
70
+ 'gray-5': '#2C2C2E',
71
+ 'gray-6': '#1C1C1E',
72
+ background: '#000000',
73
+ 'secondary-background': '#1C1C1E',
74
+ 'tertiary-background': '#2C2C2E',
75
+ label: '#FFFFFF',
76
+ 'secondary-label': 'rgba(235,235,245,0.6)'
77
+ },
78
+ variables: variables
79
+ }
80
+ }
81
+ },
82
+ typography: {
83
+ defaultTypography: 'default',
84
+ fonts: {
85
+ default: {
86
+ sans: [
87
+ 'system-ui',
88
+ '-apple-system',
89
+ 'BlinkMacSystemFont',
90
+ 'Segoe UI',
91
+ 'Roboto',
92
+ 'Helvetica Neue',
93
+ 'Arial',
94
+ 'sans-serif',
95
+ 'Apple Color Emoji',
96
+ 'Segoe UI Emoji',
97
+ 'Segoe UI Symbol'
98
+ ],
99
+ mono: [
100
+ 'SFMono-Regular',
101
+ 'ui-monospace',
102
+ 'SF Mono',
103
+ 'Menlo',
104
+ 'Monaco',
105
+ 'Consolas',
106
+ 'Liberation Mono',
107
+ 'Courier New',
108
+ 'monospace'
109
+ ],
110
+ serif: ['Merriweather', 'Georgia', 'Cambria', 'Times New Roman', 'Times', 'serif']
111
+ }
112
+ }
113
+ },
114
+ styles: {
115
+ spacing: '0.125rem', // 2px
116
+ shape: {
117
+ sm: '0.125rem', // 2px
118
+ md: '0.25rem', // 4px
119
+ lg: '0.5rem', // 8px
120
+ xl: '0.75rem', // 12px
121
+ '2xl': '1rem', // 16px
122
+ '3xl': '1.5rem', // 24px
123
+ full: '9999px' // 9999px
124
+ }
125
+ }
126
+ };
@@ -1,6 +1,10 @@
1
1
  import type { ViteDevServer } from 'vite';
2
- export declare function lapikit(): Promise<{
2
+ type Lapikit = {
3
+ config?: string;
4
+ };
5
+ export declare function lapikit({ config }?: Lapikit): Promise<{
3
6
  name: string;
4
7
  configResolved(): Promise<void>;
5
8
  configureServer(server: ViteDevServer): Promise<void>;
6
9
  }>;
10
+ export {};
@@ -2,12 +2,41 @@ import { importer } from './modules/importer.js';
2
2
  import { processCSS } from '../style/css.js';
3
3
  import { parseConfig } from './modules/config.js';
4
4
  import { terminal } from '../internal/terminal.js';
5
- export async function lapikit() {
5
+ import path from 'path';
6
+ import fs from 'fs';
7
+ import { css } from './css.js';
8
+ const app = process.cwd();
9
+ async function getLapikitConfig(filePath) {
10
+ const pathConfig = path.resolve(app, filePath);
11
+ if (!fs.existsSync(pathConfig))
12
+ process.exit(1);
13
+ const code = fs.readFileSync(pathConfig, 'utf-8');
14
+ const match = code.match(/createLapikit\s*\(\s*({[\s\S]*?})\s*\)/);
15
+ let options = {};
16
+ if (match && match[1]) {
17
+ try {
18
+ options = new Function('return ' + match[1])();
19
+ }
20
+ catch (e) {
21
+ console.error('Error parsing lapikit config:', e);
22
+ }
23
+ }
24
+ else {
25
+ console.error('Lapikit not found');
26
+ }
27
+ return options;
28
+ }
29
+ export async function lapikit({ config } = {}) {
30
+ if (config) {
31
+ const value = await getLapikitConfig(config);
32
+ // console.log(value);
33
+ await css(value);
34
+ }
6
35
  return {
7
36
  name: 'lapikit/vite.js',
8
37
  async configResolved() {
9
- const config = await importer();
10
- const result = await parseConfig(config);
38
+ const importedConfig = await importer();
39
+ const result = await parseConfig(importedConfig);
11
40
  await processCSS(result);
12
41
  terminal('info', 'lapikit is up!');
13
42
  },
@@ -0,0 +1,6 @@
1
+ import { type Writable } from 'svelte/store';
2
+ type Breakpoints = {
3
+ [key: string]: number;
4
+ };
5
+ export declare const breakpoints: Writable<Breakpoints>;
6
+ export {};
@@ -0,0 +1,14 @@
1
+ // store breakpoints and thresholds
2
+ import { writable } from 'svelte/store';
3
+ // presets
4
+ const ref = {
5
+ base: 0, // 0px
6
+ xs: 448, //28rem
7
+ sm: 640, //40rem
8
+ md: 768, //48rem
9
+ lg: 1024, //64rem
10
+ xl: 1280, //80rem
11
+ '2xl': 1536, //96rem
12
+ '3xl': 1792 //112rem
13
+ };
14
+ export const breakpoints = writable(ref);
@@ -0,0 +1,8 @@
1
+ import { type Writable } from 'svelte/store';
2
+ type ModalState = boolean | 'persistent';
3
+ export declare const modalOpen: Writable<ModalState>;
4
+ export declare const modalStack: Writable<string[]>;
5
+ export declare function setOpenModal(state: boolean | 'persistent'): void;
6
+ export declare const pushModal: (id: string) => void;
7
+ export declare const popModal: (id: string) => void;
8
+ export {};
@@ -0,0 +1,26 @@
1
+ import { disabledScroll } from '../internal/scroll.js';
2
+ import { writable } from 'svelte/store';
3
+ // presets
4
+ const refModal = false;
5
+ // states
6
+ export const modalOpen = writable(refModal);
7
+ export const modalStack = writable([]);
8
+ export function setOpenModal(state) {
9
+ modalOpen.set(state);
10
+ }
11
+ export const pushModal = (id) => {
12
+ modalStack.update((stack) => {
13
+ let values = stack;
14
+ if (!stack.includes(id))
15
+ values = [...stack, id];
16
+ disabledScroll(values.length !== 0 ? true : false);
17
+ return values;
18
+ });
19
+ };
20
+ export const popModal = (id) => {
21
+ modalStack.update((stack) => {
22
+ const newStack = stack.filter((m) => m !== id);
23
+ disabledScroll(newStack.length !== 0 ? true : false);
24
+ return newStack.length === 0 ? [] : newStack;
25
+ });
26
+ };
@@ -0,0 +1,6 @@
1
+ import { type Writable } from 'svelte/store';
2
+ type Devices = {
3
+ [key: string]: number;
4
+ };
5
+ export declare const devices: Writable<Devices>;
6
+ export {};
@@ -0,0 +1,9 @@
1
+ // store devices
2
+ import { writable } from 'svelte/store';
3
+ // presets
4
+ const ref = {
5
+ desktop: 1024, //64rem (lg)
6
+ tablet: 768, //48rem (md)
7
+ mobile: 375 //28rem (sm)
8
+ };
9
+ export const devices = writable(ref);
@@ -1,10 +1,4 @@
1
- import { type Writable } from 'svelte/store';
2
- export declare const colorScheme: Writable<'system' | 'dark' | 'light'>;
3
- export declare const colorSchemeSystem: Writable<'dark' | 'light'>;
4
- export declare const modalOpen: Writable<boolean | 'persistent'>;
5
- export declare const modalStack: Writable<string[]>;
6
- export declare function updateThemeStore(update: 'system' | 'dark' | 'light'): void;
7
- export declare function setColorScheme(scheme: 'system' | 'dark' | 'light'): void;
8
- export declare function setOpenModal(state: boolean | 'persistent'): void;
9
- export declare const pushModal: (id: string) => void;
10
- export declare const popModal: (id: string) => void;
1
+ export * from './breakpoints.js';
2
+ export * from './devices.js';
3
+ export * from './themes.js';
4
+ export * from './components.js';
@@ -1,47 +1,4 @@
1
- import { disabledScroll } from '../internal/scroll.js';
2
- import { writable } from 'svelte/store';
3
- // states
4
- const colorScheme_default = 'system';
5
- const modalOpen_default = false;
6
- const isBrowser = typeof window !== 'undefined';
7
- export const colorScheme = writable(colorScheme_default);
8
- export const colorSchemeSystem = writable('light');
9
- export const modalOpen = writable(modalOpen_default);
10
- export const modalStack = writable([]);
11
- export function updateThemeStore(update) {
12
- colorScheme.update(() => {
13
- if (isBrowser) {
14
- const ref = document.documentElement.classList;
15
- if (update === 'system')
16
- ref.remove('light', 'dark');
17
- else {
18
- ref.remove(update === 'dark' ? 'light' : 'dark');
19
- ref.add(update === 'dark' ? 'dark' : 'light');
20
- }
21
- localStorage.setItem('@lapikit/theme', update);
22
- }
23
- return update;
24
- });
25
- }
26
- export function setColorScheme(scheme) {
27
- updateThemeStore(scheme);
28
- }
29
- export function setOpenModal(state) {
30
- modalOpen.set(state);
31
- }
32
- export const pushModal = (id) => {
33
- modalStack.update((stack) => {
34
- let values = stack;
35
- if (!stack.includes(id))
36
- values = [...stack, id];
37
- disabledScroll(values.length !== 0 ? true : false);
38
- return values;
39
- });
40
- };
41
- export const popModal = (id) => {
42
- modalStack.update((stack) => {
43
- const newStack = stack.filter((m) => m !== id);
44
- disabledScroll(newStack.length !== 0 ? true : false);
45
- return newStack.length === 0 ? [] : newStack;
46
- });
47
- };
1
+ export * from './breakpoints.js';
2
+ export * from './devices.js';
3
+ export * from './themes.js';
4
+ export * from './components.js';
@@ -0,0 +1,8 @@
1
+ import { type Writable } from 'svelte/store';
2
+ type PreferColorScheme = 'system' | 'dark' | 'light';
3
+ export declare const colorScheme: Writable<PreferColorScheme>;
4
+ export declare const colorSchemeSystem: Writable<'dark' | 'light'>;
5
+ export declare const theme: Writable<string>;
6
+ export declare function useColorScheme(scheme: PreferColorScheme, key?: string): void;
7
+ export declare function useTheme(name: string, key?: string): void;
8
+ export {};
@@ -0,0 +1,34 @@
1
+ import { writable } from 'svelte/store';
2
+ // presets
3
+ const colorSchemeRef = 'system';
4
+ const themeRef = 'lapikit';
5
+ // states
6
+ const isBrowser = typeof window !== 'undefined';
7
+ export const colorScheme = writable(colorSchemeRef);
8
+ export const colorSchemeSystem = writable('light');
9
+ export const theme = writable(themeRef);
10
+ export function useColorScheme(scheme, key = '@lapikit/color-scheme') {
11
+ colorScheme.update(() => {
12
+ if (isBrowser) {
13
+ const ref = document.documentElement.classList;
14
+ if (scheme === 'system')
15
+ ref.remove('light', 'dark');
16
+ else {
17
+ ref.remove(scheme === 'dark' ? 'light' : 'dark');
18
+ ref.add(scheme === 'dark' ? 'dark' : 'light');
19
+ }
20
+ localStorage.setItem(key, scheme);
21
+ }
22
+ return scheme;
23
+ });
24
+ }
25
+ export function useTheme(name, key = '@lapikit/theme') {
26
+ theme.update(() => {
27
+ if (isBrowser) {
28
+ const html = document.documentElement;
29
+ html.setAttribute('data-theme', name);
30
+ localStorage.setItem(key, name);
31
+ }
32
+ return name;
33
+ });
34
+ }
@@ -0,0 +1 @@
1
+ export declare function valueToPx(value: string | number): number;
@@ -0,0 +1,17 @@
1
+ export function valueToPx(value) {
2
+ if (typeof value === 'number')
3
+ return value;
4
+ if (typeof value === 'string') {
5
+ if (value.endsWith('rem')) {
6
+ return parseFloat(value) * 16;
7
+ }
8
+ if (value.endsWith('em')) {
9
+ return parseFloat(value) * 16;
10
+ }
11
+ if (value.endsWith('px')) {
12
+ return parseFloat(value);
13
+ }
14
+ return parseFloat(value);
15
+ }
16
+ return 0;
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lapikit",
3
- "version": "0.0.0-insiders.bd609af",
3
+ "version": "0.0.0-insiders.c3399e0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -59,7 +59,8 @@
59
59
  "./actions": {
60
60
  "default": "./dist/actions/index.js"
61
61
  },
62
- "./css": "./dist/styles.css"
62
+ "./css": "./dist/styles.css",
63
+ "./styles": "./dist/colors.css"
63
64
  },
64
65
  "peerDependencies": {
65
66
  "svelte": "^5.0.0"