spoko-design-system 0.8.2 → 0.8.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoko-design-system",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "private": false,
5
5
  "main": "./index.ts",
6
6
  "module": "./index.ts",
@@ -40,7 +40,7 @@
40
40
  "spoko design system"
41
41
  ],
42
42
  "dependencies": {
43
- "@algolia/client-search": "^5.29.0",
43
+ "@algolia/client-search": "^5.30.0",
44
44
  "@astrojs/mdx": "^4.3.0",
45
45
  "@astrojs/node": "^9.2.2",
46
46
  "@astrojs/sitemap": "^3.4.1",
@@ -57,57 +57,57 @@
57
57
  "@iconify-json/eos-icons": "^1.2.2",
58
58
  "@iconify-json/et": "^1.2.1",
59
59
  "@iconify-json/flowbite": "^1.2.5",
60
- "@iconify-json/fluent": "^1.2.25",
60
+ "@iconify-json/fluent": "^1.2.26",
61
61
  "@iconify-json/fluent-emoji": "1.2.3",
62
62
  "@iconify-json/ic": "^1.2.2",
63
63
  "@iconify-json/icon-park-outline": "^1.2.2",
64
64
  "@iconify-json/la": "^1.2.1",
65
- "@iconify-json/material-symbols-light": "^1.2.27",
65
+ "@iconify-json/material-symbols-light": "^1.2.28",
66
66
  "@iconify-json/mdi": "^1.2.3",
67
67
  "@iconify-json/noto-v1": "^1.2.2",
68
- "@iconify-json/octicon": "^1.2.6",
68
+ "@iconify-json/octicon": "^1.2.7",
69
69
  "@iconify-json/ph": "^1.2.2",
70
- "@iconify-json/simple-icons": "^1.2.39",
70
+ "@iconify-json/simple-icons": "^1.2.41",
71
71
  "@iconify-json/system-uicons": "^1.2.2",
72
72
  "@iconify-json/uil": "^1.2.3",
73
- "@iconify/json": "^2.2.351",
73
+ "@iconify/json": "^2.2.354",
74
74
  "@iconify/vue": "^5.0.0",
75
75
  "@playform/compress": "^0.2.0",
76
76
  "@playform/inline": "^0.1.2",
77
- "@unocss/astro": "66.2.3",
78
- "@unocss/preset-attributify": "66.2.3",
79
- "@unocss/preset-typography": "66.2.3",
80
- "@unocss/preset-uno": "66.2.3",
81
- "@unocss/preset-web-fonts": "66.2.3",
82
- "@unocss/preset-wind": "66.2.3",
83
- "@unocss/reset": "66.2.3",
77
+ "@unocss/astro": "66.3.2",
78
+ "@unocss/preset-attributify": "66.3.2",
79
+ "@unocss/preset-typography": "66.3.2",
80
+ "@unocss/preset-uno": "66.3.2",
81
+ "@unocss/preset-web-fonts": "66.3.2",
82
+ "@unocss/preset-wind": "66.3.2",
83
+ "@unocss/reset": "66.3.2",
84
84
  "@vite-pwa/astro": "^1.1.0",
85
- "@vueuse/core": "^13.4.0",
85
+ "@vueuse/core": "^13.5.0",
86
86
  "astro-i18next": "1.0.0-beta.21",
87
87
  "astro-icon": "^1.1.5",
88
88
  "astro-meta-tags": "^0.3.2",
89
89
  "astro-navbar": "^2.4.0",
90
90
  "astro-pagefind": "^1.8.3",
91
91
  "astro-remote": "^0.3.4",
92
- "dotenv": "^16.5.0",
93
- "i18next": "^25.2.1",
92
+ "dotenv": "^17.0.1",
93
+ "i18next": "^25.3.0",
94
94
  "i18next-browser-languagedetector": "^8.2.0",
95
95
  "i18next-fs-backend": "^2.6.0",
96
96
  "i18next-http-backend": "^3.0.2",
97
97
  "i18next-vue": "^5.3.0",
98
- "swiper": "^11.2.8",
99
- "unocss": "66.2.3",
98
+ "swiper": "^11.2.10",
99
+ "unocss": "66.3.2",
100
100
  "vue": "^3.5.17"
101
101
  },
102
102
  "devDependencies": {
103
103
  "@types/gtag.js": "^0.0.20",
104
- "@types/node": "^24.0.3",
105
- "@unocss/transformer-variant-group": "66.2.3",
106
- "@vitejs/plugin-vue": "^5.2.4",
104
+ "@types/node": "^24.0.10",
105
+ "@unocss/transformer-variant-group": "66.3.2",
106
+ "@vitejs/plugin-vue": "^6.0.0",
107
107
  "@vue/compiler-sfc": "^3.5.17",
108
- "astro": "^5.10.1",
108
+ "astro": "^5.10.2",
109
109
  "unocss": "^0.65.0",
110
- "vite": "^6.3.5"
110
+ "vite": "^7.0.0"
111
111
  },
112
112
  "packageManager": "pnpm@9.15.3",
113
113
  "pnpm": {
@@ -7,21 +7,17 @@ interface ColorCode {
7
7
  name: string;
8
8
  }
9
9
 
10
- interface PaintMark {
11
- count: number;
12
- color: string;
13
- }
14
-
15
10
  interface TableItem {
16
11
  id: string;
17
12
  name: string;
18
- value: unknown;
13
+ value: unknown; // Może być string, number, boolean, array (ColorCode[] lub string[])
19
14
  translated?: boolean;
20
15
  icon?: boolean;
21
16
  isArrayValue?: boolean;
22
- isColorArray?: boolean;
23
- isPaintMarks?: boolean;
24
- isGenericArray?: boolean;
17
+ isColorArray?: boolean; // dla product.colors (color_ids)
18
+ isPaintMarks?: boolean; // dla product.paint_marks_text
19
+ isGenericArray?: boolean; // dla ogólnych tablic stringów (np. position)
20
+ isForExteriorColour?: boolean; // Ta flaga będzie ustawiana przez getProductDetails na true, jeśli 'value' jest tablicą
25
21
  }
26
22
 
27
23
  interface GroupedLink {
@@ -37,26 +33,34 @@ const props = defineProps({
37
33
  caption: { type: String, default: null }
38
34
  });
39
35
 
40
- // Function for checking whether a value is a link
36
+ // Function to check if a value is a link
41
37
  const isLink = (id: string) => {
42
38
  return ['blog', 'youtube', 'vimeo'].includes(id);
43
39
  };
44
40
 
45
- // Function for checking if it's a color array
41
+ // Function to check if it's a color array (for 'color_ids' field from product.colors)
42
+ // This will still apply to the 'color' detail if its value is an array of ColorCode objects
46
43
  const isColorArray = (item: TableItem) => {
47
- return item.isColorArray && Array.isArray(item.value);
44
+ const colorIds = ['color', 'thread-color']; // lista ID które są kolorami
45
+ return (item.isColorArray || colorIds.includes(item.id)) && Array.isArray(item.value);
48
46
  };
49
47
 
50
- // Function for checking if it's paint marks
48
+ // Function to check if it's paint marks (value is now a string from API)
51
49
  const isPaintMarks = (item: TableItem) => {
52
- return item.isPaintMarks && Array.isArray(item.value);
50
+ return item.isPaintMarks && typeof item.value === 'string';
53
51
  };
54
52
 
55
- // Function for checking if it's a generic array
53
+ // Function to check if it's a generic array (e.g., for position)
56
54
  const isGenericArray = (item: TableItem) => {
57
55
  return item.isGenericArray && Array.isArray(item.value);
58
56
  };
59
57
 
58
+ // ✅ Zaktualizowana funkcja: Sprawdzamy ID i czy value jest faktycznie tablicą ColorCode[]
59
+ const isForExteriorColour = (item: TableItem) => {
60
+ return item.id === 'for-exterior-colour' && Array.isArray(item.value);
61
+ };
62
+
63
+
60
64
  // Function to check if value is HTML string (fallback)
61
65
  const isHtmlValue = (value: unknown): boolean => {
62
66
  return typeof value === 'string' && (value.includes('<span') || value.includes('<br>'));
@@ -64,13 +68,13 @@ const isHtmlValue = (value: unknown): boolean => {
64
68
 
65
69
  // Function for specifying header text
66
70
  const getHeaderText = (row: TableItem | GroupedLink) => {
67
- // For the blog, we use id instead of name
68
71
  if (row.id === 'blog') {
69
72
  return row.id.charAt(0).toUpperCase() + row.id.slice(1);
70
73
  }
71
-
72
- // For other types, we use name (if it is GroupedLink, there is no name)
73
- return 'name' in row ? row.name : row.id.charAt(0).toUpperCase() + row.id.slice(1);
74
+ // Użyj `name` z obiektu `TableItem`, jeśli istnieje, w przeciwnym razie sformatuj `id`.
75
+ return 'name' in row ? row.name : row.id.split('-')
76
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
77
+ .join(' ');
74
78
  };
75
79
 
76
80
  // Function to determine the icon class for a link type
@@ -89,37 +93,43 @@ const getLinkIconClass = (linkId: string) => {
89
93
 
90
94
  // Grouping of elements by id
91
95
  const groupedItems = computed(() => {
96
+ // ✅ Add validation to ensure props.items is an array
97
+ if (!Array.isArray(props.items)) {
98
+ console.warn('ProductDetailsList: items prop is not an array:', props.items);
99
+ return [];
100
+ }
101
+
92
102
  const result: (TableItem | GroupedLink)[] = [];
93
103
  const linkGroups = new Map<string, GroupedLink>();
94
-
95
- // We process all elements
104
+
105
+ // Process all elements
96
106
  props.items.forEach(item => {
97
107
  // If it's a link (blog, youtube, vimeo)
98
108
  if (isLink(item.id)) {
99
109
  // Add a link to the relevant group
100
110
  if (!linkGroups.has(item.id)) {
101
- linkGroups.set(item.id, {
102
- id: item.id,
103
- links: []
111
+ linkGroups.set(item.id, {
112
+ id: item.id,
113
+ links: []
104
114
  });
105
115
  }
106
-
116
+
107
117
  // Add link to the relevant group
108
118
  linkGroups.get(item.id)?.links.push({
109
119
  name: item.name,
110
120
  value: item.value as string
111
121
  });
112
122
  } else {
113
- // If it is not a link, we add it normally to the results
123
+ // If it's not a link, add it normally to the results
114
124
  result.push(item);
115
125
  }
116
126
  });
117
-
127
+
118
128
  // Add all link groups at the end
119
129
  linkGroups.forEach(group => {
120
130
  result.push(group);
121
131
  });
122
-
132
+
123
133
  return result;
124
134
  });
125
135
  </script>
@@ -135,63 +145,72 @@ const groupedItems = computed(() => {
135
145
  </colgroup>
136
146
  <tbody>
137
147
  <tr v-for="row, index in groupedItems" :key="index" class="details-table-row">
138
- <!-- We use the getHeaderText function to specify the header text -->
139
- <ProductDetailName
140
- as="th"
141
- :text="getHeaderText(row)"
142
- class="details-table-header"
143
- />
144
-
145
- <!-- Handling link groups -->
148
+ <ProductDetailName as="th" :text="getHeaderText(row)" class="details-table-header" />
149
+
146
150
  <td v-if="'links' in row" class="details-table-cell">
147
151
  <ul class="list-none p-0 m-0">
148
152
  <li v-for="(link, linkIndex) in row.links" :key="linkIndex" class="mb-2 last:mb-0 flex items-center">
149
- <span :class="[getLinkIconClass(row.id), 'leading-none inline-block mr-2 w-4 min-w-4 h-4 text-gray-400']" />
153
+ <span
154
+ :class="[getLinkIconClass(row.id), 'leading-none inline-block mr-2 w-4 min-w-4 h-4 text-gray-400']" />
150
155
  <a :href="link.value" target="_blank" rel="noopener noreferrer" class="link-primary">
151
156
  {{ link.name }}
152
157
  </a>
153
158
  </li>
154
159
  </ul>
155
160
  </td>
156
-
157
- <!-- Special handling for color arrays (already translated) -->
161
+
158
162
  <td v-else-if="'id' in row && isColorArray(row)" class="details-table-cell">
159
- <ul>
160
- <li v-for="(colorItem, colorIndex) in (row.value as ColorCode[])" :key="colorIndex"
161
- class="flex items-center gap-1 mb-1 last:mb-0">
162
- <code>
163
- {{ colorItem.code }}
164
- </code>
165
- <span class="text-gray-400">-</span>
166
- <span class="text-gray-700 dark:text-gray-300">{{ colorItem.name }}</span>
167
- </li>
163
+ <ul class="list-none p-0 m-0">
164
+ <li v-for="(colorItem, colorIndex) in (row.value as ColorCode[])" :key="colorIndex"
165
+ class="flex items-center gap-1 mb-1 last:mb-0">
166
+
167
+ <template v-if="colorItem.code">
168
+ <code class="font-mono text-sm">
169
+ {{ colorItem.code }}
170
+ </code>
171
+ <span class="text-gray-400">-</span>
172
+ </template>
173
+ <span class="text-gray-700 dark:text-gray-300">{{ colorItem.name }}</span>
174
+ </li>
168
175
  </ul>
169
176
  </td>
170
-
171
- <!-- Special handling for paint marks (already translated) -->
177
+
172
178
  <td v-else-if="'id' in row && isPaintMarks(row)" class="details-table-cell">
173
179
  <span class="text-gray-700 dark:text-gray-300">{{ row.value }}</span>
174
180
  </td>
175
-
176
- <!-- Generic array handling (bullet list) -->
181
+
182
+ <td v-else-if="'id' in row && isForExteriorColour(row)" class="details-table-cell">
183
+ <ul class="list-none p-0 m-0">
184
+ <li v-for="(colorEntry, colourIndex) in (row.value as ColorCode[])" :key="colourIndex"
185
+ class="flex items-center gap-1 mb-1 last:mb-0">
186
+
187
+ <template v-if="colorEntry.code">
188
+ <code class="font-mono text-sm">
189
+ {{ colorEntry.code }}
190
+ </code>
191
+ <span class="text-gray-400">-</span>
192
+ </template>
193
+ <span class="text-gray-700 dark:text-gray-300">{{ colorEntry.name }}</span>
194
+ </li>
195
+ </ul>
196
+ </td>
197
+
177
198
  <td v-else-if="'id' in row && isGenericArray(row)" class="details-table-cell">
178
199
  <ul class="list-none p-0 m-0">
179
- <li v-for="(item, itemIndex) in (row.value as string[])" :key="itemIndex"
180
- class="flex items-start gap-2 mb-1 last:mb-0 leading-relaxed">
200
+ <li v-for="(item, itemIndex) in (row.value as string[])" :key="itemIndex"
201
+ class="flex items-start gap-2 mb-1 last:mb-0 leading-relaxed">
181
202
  <span class="text-gray-500 font-bold flex-shrink-0 mt-0.5">·</span>
182
203
  <span class="text-gray-700 dark:text-gray-300 text-sm">{{ item }}</span>
183
204
  </li>
184
205
  </ul>
185
206
  </td>
186
-
187
- <!-- Handling HTML values (fallback for already formatted HTML) -->
207
+
188
208
  <td v-else-if="'id' in row && isHtmlValue(row.value)" class="details-table-cell" v-html="row.value"></td>
189
-
190
- <!-- Support for standard types -->
209
+
191
210
  <slot v-else-if="'id' in row" :name="row.id">
192
211
  <td class="details-table-cell">{{ row.value }}</td>
193
212
  </slot>
194
213
  </tr>
195
214
  </tbody>
196
215
  </table>
197
- </template>
216
+ </template>
@@ -91,10 +91,10 @@ const navItems = [
91
91
  <div>
92
92
  <Headline underline as="div" class="mx-auto text-gray-900" textSize="3xl">Download:</Headline>
93
93
  <div class="grid grid-flow-col gap-4 auto-cols-max text-6xl mb-12">
94
- <a href="https://www.npmjs.com/package/spoko-design-system" rel="noopener" title="npm page" class="hover:text-accent-lightest">
94
+ <a href="https://www.npmjs.com/package/spoko-design-system" rel="noopener" title="npm page" class="hover:text-accent-light">
95
95
  <Icon name="mdi:npm"/>
96
96
  </a>
97
- <a href="https://github.com/polo-blue/sds" rel="noopener" title="Github Page" class="hover:text-accent-lightest">
97
+ <a href="https://github.com/polo-blue/sds" rel="noopener" title="Github Page" class="hover:text-accent-light">
98
98
  <Icon name="mdi:github"/>
99
99
  </a>
100
100
  </div>
@@ -109,7 +109,7 @@ export const componentShortcuts = [
109
109
  ['breadcrumb-back-btn', 'flex items-center px-3 sm:px-0 py-4.25 sm:py-1 hover:text-accent-light whitespace-nowrap my-auto'],
110
110
 
111
111
  // PostCategories
112
- ['category-link-base', 'text-sm sm:text-base text-accent-lightest uppercase hover:text-blue-500 transition-colors'],
112
+ ['category-link-base', 'text-sm sm:text-base text-accent-light uppercase hover:text-blue-500 transition-colors'],
113
113
  ['category-link-active', 'text-blue-500'],
114
114
 
115
115
  // Details table
@@ -121,7 +121,7 @@ export const TYPOGRAPHY = {
121
121
  export const PRODUCT_STYLES = {
122
122
  thumb: {
123
123
  base: 'h-full w-full object-cover object-center transform scale-100 group-hover:scale-110 absolute inset-0 will-change-transform bg-neutral-lightest',
124
- container: `${aspectRatios['4/3']} ${LAYOUT.flex.alignCenter} mb-3 sm:mb-0 ${IMAGE_STYLES.overlay}`,
124
+ container: `${aspectRatios['4/3']} ${LAYOUT.flex.alignCenter} mb-3 sm:mb-auto ${IMAGE_STYLES.overlay}`,
125
125
  },
126
126
  link: {
127
127
  base: 'relative flex w-full bg-white after:(absolute bg-accent-light w-[calc(100%-1rem)] left-0 h-px top-[calc(100%-1px)] bottom-1 content-empty scale-x-0 transition-transform-300 origin-top-right) hover:after:(origin-top-left scale-x-100)',