spoko-design-system 1.3.0 → 1.3.2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [1.3.2](https://github.com/polo-blue/sds/compare/v1.3.1...v1.3.2) (2025-10-07)
2
+
3
+ ## [1.3.1](https://github.com/polo-blue/sds/compare/v1.3.0...v1.3.1) (2025-10-05)
4
+
1
5
  ## [1.3.0](https://github.com/polo-blue/sds/compare/v1.2.2...v1.3.0) (2025-10-05)
2
6
 
3
7
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoko-design-system",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "private": false,
5
5
  "main": "./index.ts",
6
6
  "module": "./index.ts",
@@ -74,7 +74,7 @@ const isLast = (index: number) => {
74
74
  <meta
75
75
  itemprop="position"
76
76
  content="1"
77
- />
77
+ >
78
78
  </li>
79
79
  <li
80
80
  v-for="(crumb, index) in breadcrumbs"
@@ -84,7 +84,10 @@ const isLast = (index: number) => {
84
84
  itemscope
85
85
  itemtype="https://schema.org/ListItem"
86
86
  >
87
- <span v-if="index > 0 || props.showHome" class="text-gray-400 px-1 py-4.25 sm:py-1">/</span>
87
+ <span
88
+ v-if="index > 0 || props.showHome"
89
+ class="text-gray-400 px-1 py-4.25 sm:py-1"
90
+ >/</span>
88
91
 
89
92
  <a
90
93
  v-if="!isLast(index)"
@@ -93,7 +96,10 @@ const isLast = (index: number) => {
93
96
  itemprop="item"
94
97
  :title="`Polo 6R ${crumb.name}`"
95
98
  >
96
- <strong class="font-normal" itemprop="name">{{ crumb.name }}</strong>
99
+ <strong
100
+ class="font-normal"
101
+ itemprop="name"
102
+ >{{ crumb.name }}</strong>
97
103
  </a>
98
104
  <a
99
105
  v-else
@@ -102,15 +108,22 @@ const isLast = (index: number) => {
102
108
  :title="`Polo 6R ${crumb.name} ${productNumber}`"
103
109
  itemprop="item"
104
110
  >
105
- <span class="font-normal" itemprop="name">
111
+ <span
112
+ class="font-normal"
113
+ itemprop="name"
114
+ >
106
115
  <span v-html="crumb.name" />
107
- <b v-if="productNumber" class="hidden sm:inline font-normal ml-1"
108
- >&nbsp;{{ productNumber }}</b
109
- >
116
+ <b
117
+ v-if="productNumber"
118
+ class="hidden sm:inline font-normal ml-1"
119
+ >&nbsp;{{ productNumber }}</b>
110
120
  </span>
111
121
  </a>
112
122
 
113
- <meta itemprop="position" :content="String(props.showHome ? index + 2 : index + 1)" />
123
+ <meta
124
+ itemprop="position"
125
+ :content="String(props.showHome ? index + 2 : index + 1)"
126
+ >
114
127
  </li>
115
128
  </ul>
116
129
  </nav>
@@ -27,11 +27,18 @@ const { copy, copied } = useClipboard({ source, legacy: true });
27
27
  </script>
28
28
 
29
29
  <template>
30
- <button :aria-label="texts.copy" class="btn-copy has-tooltip" @click="copy()">
30
+ <button
31
+ :aria-label="texts.copy"
32
+ class="btn-copy has-tooltip"
33
+ @click="copy()"
34
+ >
31
35
  <span
32
36
  :class="`tooltip rounded-full btn-copy-text ${tooltipClasses}`"
33
37
  :data-text="!copied ? texts.copy : texts.copied"
34
38
  />
35
- <span i-ph-copy-simple-light class="leading-none w-full h-full" />
39
+ <span
40
+ i-ph-copy-simple-light
41
+ class="leading-none w-full h-full"
42
+ />
36
43
  </button>
37
44
  </template>
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <a :href="href" class="category-link" :class="{ active: active }">
2
+ <a
3
+ :href="href"
4
+ class="category-link"
5
+ :class="{ active: active }"
6
+ >
3
7
  {{ text }}
4
8
  </a>
5
9
  </template>
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <button class="category-toggler md:w-8" type="button" aria-label="toggle menu">
2
+ <button
3
+ class="category-toggler md:w-8"
4
+ type="button"
5
+ aria-label="toggle menu"
6
+ >
3
7
  <slot />
4
8
  </button>
5
9
  </template>
@@ -16,11 +16,18 @@ const props = defineProps({
16
16
  </script>
17
17
 
18
18
  <template>
19
- <h2 v-if="props.caption" class="features-list-caption">
19
+ <h2
20
+ v-if="props.caption"
21
+ class="features-list-caption"
22
+ >
20
23
  {{ props.caption }}
21
24
  </h2>
22
25
  <ul class="features-list-ul">
23
- <li v-for="(item, index) in props.items" :key="index" class="features-list-item">
26
+ <li
27
+ v-for="(item, index) in props.items"
28
+ :key="index"
29
+ class="features-list-item"
30
+ >
24
31
  {{ item }}
25
32
  </li>
26
33
  </ul>
@@ -1,20 +1,47 @@
1
1
  <template>
2
- <div class="relative flex" title="FUCK PUTIN! FUCK RUZZIA!">
3
- <div i-mdi:tank class="inline-block bg-ukraine mr-1 mt-0.5" />
4
- <div i-mdi:tank class="inline-block bg-ukraine mr-1 mt-0.5" />
5
- <div i-mdi:tank class="inline-block bg-ukraine mr-5 mt-0.5" />
2
+ <div
3
+ class="relative flex"
4
+ title="FUCK PUTIN! FUCK RUZZIA!"
5
+ >
6
+ <div
7
+ i-mdi:tank
8
+ class="inline-block bg-ukraine mr-1 mt-0.5"
9
+ />
10
+ <div
11
+ i-mdi:tank
12
+ class="inline-block bg-ukraine mr-1 mt-0.5"
13
+ />
14
+ <div
15
+ i-mdi:tank
16
+ class="inline-block bg-ukraine mr-5 mt-0.5"
17
+ />
6
18
  <div class="relative">
7
- <div class="inline-block absolute" i-noto-v1:flag-for-flag-russia />
8
- <div i-emojione:fire class="inline-block absolute -mt-1 animate-ping animate-pulseR" />
19
+ <div
20
+ class="inline-block absolute"
21
+ i-noto-v1:flag-for-flag-russia
22
+ />
23
+ <div
24
+ i-emojione:fire
25
+ class="inline-block absolute -mt-1 animate-ping animate-pulseR"
26
+ />
9
27
  </div>
10
28
  <div class="absolute left-0 animate-bull animate-bull--1 -mt-1">
11
- <div i-mdi:bullet class="rotate-90 inline-block bg-yellow" />
29
+ <div
30
+ i-mdi:bullet
31
+ class="rotate-90 inline-block bg-yellow"
32
+ />
12
33
  </div>
13
34
  <div class="absolute left-0 animate-bull animate-bull animate-bull--2 -mt-1">
14
- <div i-mdi:bullet class="rotate-90 inline-block bg-yellow" />
35
+ <div
36
+ i-mdi:bullet
37
+ class="rotate-90 inline-block bg-yellow"
38
+ />
15
39
  </div>
16
40
  <div class="absolute left-0 animate-bull animate-bull--3 -mt-1">
17
- <div i-mdi:bullet class="rotate-90 inline-block bg-yellow" />
41
+ <div
42
+ i-mdi:bullet
43
+ class="rotate-90 inline-block bg-yellow"
44
+ />
18
45
  </div>
19
46
  </div>
20
47
  </template>
@@ -125,18 +125,31 @@ const handleBlur = (event: globalThis.FocusEvent) => emit('blur', event);
125
125
  @input="handleInput"
126
126
  @focus="handleFocus"
127
127
  @blur="handleBlur"
128
- />
128
+ >
129
129
 
130
- <label :for="id" :class="labelClass" style="transform-origin: top left">
130
+ <label
131
+ :for="id"
132
+ :class="labelClass"
133
+ style="transform-origin: top left"
134
+ >
131
135
  {{ label }}
132
- <span v-if="required" class="text-red-500 ml-1">*</span>
136
+ <span
137
+ v-if="required"
138
+ class="text-red-500 ml-1"
139
+ >*</span>
133
140
  </label>
134
141
 
135
- <div v-if="error && typeof error === 'string'" class="input-error-message">
142
+ <div
143
+ v-if="error && typeof error === 'string'"
144
+ class="input-error-message"
145
+ >
136
146
  {{ error }}
137
147
  </div>
138
148
 
139
- <div v-if="success && typeof success === 'string'" class="input-success-message">
149
+ <div
150
+ v-if="success && typeof success === 'string'"
151
+ class="input-success-message"
152
+ >
140
153
  {{ success }}
141
154
  </div>
142
155
  </div>
@@ -7,13 +7,23 @@ const colorCategories = Object.entries(colors);
7
7
 
8
8
  <template>
9
9
  <div class="flex flex-col space-y-12">
10
- <div v-for="[category, shades] in colorCategories" :key="category">
10
+ <div
11
+ v-for="[category, shades] in colorCategories"
12
+ :key="category"
13
+ >
11
14
  <h3 class="capitalize">
12
15
  {{ category }}
13
16
  </h3>
14
17
  <div class="grid grid-cols-3 md:grid-cols-9">
15
- <div v-for="(value, name) in shades" :key="name" class="mb-6">
16
- <div class="h-12 transition-all" :style="`background: ${value}`" />
18
+ <div
19
+ v-for="(value, name) in shades"
20
+ :key="name"
21
+ class="mb-6"
22
+ >
23
+ <div
24
+ class="h-12 transition-all"
25
+ :style="`background: ${value}`"
26
+ />
17
27
  <div class="text-sm flex flex-col text-center font-mono text-slate-500">
18
28
  <span>{{ name }}</span>
19
29
  <span class="uppercase text-xs">{{ value }}</span>
@@ -8,11 +8,10 @@ const props = defineProps<{
8
8
  <label class="group text-left w-full max-w-xs flex flex-col">
9
9
  <span
10
10
  class="group-hover:text-blue-medium ml-2 text-slate-600 text-sm group-focus-within:text-blue-medium"
11
- >{{ props.label }}</span
12
- >
11
+ >{{ props.label }}</span>
13
12
  <input
14
13
  class="group-hover:border-blue-lightest border px-4 py-2 transition-colors rounded-md w-full focus:ring focus:outline-none focus:border-blue-medium"
15
14
  type="text"
16
- />
15
+ >
17
16
  </label>
18
17
  </template>
@@ -21,7 +21,10 @@ const props = defineProps({
21
21
  </script>
22
22
 
23
23
  <template>
24
- <component :is="props.as" :class="props.class">
24
+ <component
25
+ :is="props.as"
26
+ :class="props.class"
27
+ >
25
28
  {{ props.number }}
26
29
  </component>
27
30
  </template>
@@ -9,7 +9,10 @@ const props = defineProps({
9
9
  </script>
10
10
 
11
11
  <template>
12
- <button class="product-button" :class="props.shadow ? 'drop-shadow hover:(drop-shadow-md)' : ''">
12
+ <button
13
+ class="product-button"
14
+ :class="props.shadow ? 'drop-shadow hover:(drop-shadow-md)' : ''"
15
+ >
13
16
  <slot />
14
17
  </button>
15
18
  </template>
@@ -15,7 +15,10 @@ const props = defineProps({
15
15
 
16
16
  <template>
17
17
  <div class="font-bold detail-name w-full sm:w-50 flex">
18
- <span class="colon-after" :class="styles && styles.length ? styles : 'mt-auto'">
18
+ <span
19
+ class="colon-after"
20
+ :class="styles && styles.length ? styles : 'mt-auto'"
21
+ >
19
22
  {{ props.text }}
20
23
  </span>
21
24
  </div>
@@ -30,18 +30,28 @@ const props = defineProps({
30
30
 
31
31
  <template>
32
32
  <div v-if="details && details.length">
33
- <template v-for="(detail, index) in details" :key="index">
33
+ <template
34
+ v-for="(detail, index) in details"
35
+ :key="index"
36
+ >
34
37
  <!-- PDP PAGE - PRODUCT ROW -->
35
38
  <!-- <pre>{{ JSON.stringify(details) }}</pre> -->
36
39
  <li
37
40
  v-if="props.small"
38
41
  class="text-xs md:text-sm text-slate-darkest dark:text-neutral-light leading-tight font-textlight md:font-textregular"
39
42
  >
40
- <span v-if="detail.id" class="inline-block mr-1 items--0">
43
+ <span
44
+ v-if="detail.id"
45
+ class="inline-block mr-1 items--0"
46
+ >
41
47
  {{ getTranslation(`detail.${detail.id}`) }}:
42
48
  </span>
43
49
 
44
- <span v-if="detail.translated" :class="detail.id ? 'font-semibold' : ''" class="items--1">
50
+ <span
51
+ v-if="detail.translated"
52
+ :class="detail.id ? 'font-semibold' : ''"
53
+ class="items--1"
54
+ >
45
55
  {{ detail.value }}
46
56
  </span>
47
57
 
@@ -49,16 +59,26 @@ const props = defineProps({
49
59
  v-else-if="detail.value !== undefined && detail.id === 'color' && detail.isArrayValue"
50
60
  class="items--2 inline-block"
51
61
  >
52
- <span v-for="(color, indexColor) in detail.value" :key="indexColor" class="comma">
62
+ <span
63
+ v-for="(color, indexColor) in detail.value"
64
+ :key="indexColor"
65
+ class="comma"
66
+ >
53
67
  {{ color['name'] }}
54
68
  </span>
55
69
  </div>
56
70
 
57
- <span v-else-if="detail.id !== 'paint-marks' && !detail.isArrayValue" class="items--3">
71
+ <span
72
+ v-else-if="detail.id !== 'paint-marks' && !detail.isArrayValue"
73
+ class="items--3"
74
+ >
58
75
  {{ locale === 'en' ? String(detail.value).replace(/,/g, '.') : String(detail.value) }}
59
76
  </span>
60
77
 
61
- <span v-else-if="detail.id && detail.id === 'paint-marks'" class="items items--4">
78
+ <span
79
+ v-else-if="detail.id && detail.id === 'paint-marks'"
80
+ class="items items--4"
81
+ >
62
82
  {{ detail.value }}
63
83
  <!-- <span v-for="(mark, index2) in JSON.parse(String(detail.value))" :key="index2" class="item">
64
84
  {{ mark[0] }} x <span>{{ getTranslation(`color.${mark[1]}`) }}</span>
@@ -71,8 +91,14 @@ const props = defineProps({
71
91
  class="text-sm mt-1 md:mt-4 mb-4 grid grid-cols-2 sm:(grid-cols-details-desktop grid-flow-col auto-cols-max) gap-4"
72
92
  >
73
93
  <!-- PRODUCT CARD -->
74
- <ProductDetailName v-if="detail.id" :text="getTranslation(`detail.${detail.id}`)" />
75
- <div v-if="detail.value" class="leading-4 flex items-end">
94
+ <ProductDetailName
95
+ v-if="detail.id"
96
+ :text="getTranslation(`detail.${detail.id}`)"
97
+ />
98
+ <div
99
+ v-if="detail.value"
100
+ class="leading-4 flex items-end"
101
+ >
76
102
  <span
77
103
  v-if="detail.translated && !detail.isArrayValue"
78
104
  :class="detail.id === 'light-function' ? 'whitespace-pre-line' : ''"
@@ -80,25 +106,34 @@ const props = defineProps({
80
106
  {{ getTranslation(`detail.value.${detail.value}`) }}
81
107
  </span>
82
108
 
83
- <span v-else-if="detail.id !== 'paint-marks' && !detail.isArrayValue" class="">
109
+ <span
110
+ v-else-if="detail.id !== 'paint-marks' && !detail.isArrayValue"
111
+ class=""
112
+ >
84
113
  {{ detail.value }}
85
114
  </span>
86
115
 
87
116
  <span
88
117
  v-else-if="
89
118
  detail.value !== undefined &&
90
- detail.id === 'for-exterior-colour' &&
91
- detail.isArrayValue
119
+ detail.id === 'for-exterior-colour' &&
120
+ detail.isArrayValue
92
121
  "
93
122
  class=""
94
123
  >
95
- <div v-for="(color, indexColor) in JSON.parse(String(detail.value))" :key="indexColor">
124
+ <div
125
+ v-for="(color, indexColor) in JSON.parse(String(detail.value))"
126
+ :key="indexColor"
127
+ >
96
128
  <span class="font-mono">{{ color }}</span> -
97
129
  {{ getTranslation(`colorCodes.${color}`) }}
98
130
  </div>
99
131
  </span>
100
132
 
101
- <span v-else-if="detail.id && detail.id === 'paint-marks'" class="items">
133
+ <span
134
+ v-else-if="detail.id && detail.id === 'paint-marks'"
135
+ class="items"
136
+ >
102
137
  <span
103
138
  v-for="(mark, markIndex) in JSON.parse(String(detail.value))"
104
139
  :key="markIndex"
@@ -107,8 +142,15 @@ const props = defineProps({
107
142
  {{ mark[0] }} x <span>{{ getTranslation(`color.${mark[1]}`) }}</span>
108
143
  </span>
109
144
  </span>
110
- <ul v-else-if="detail.id && detail.isArrayValue" class="items">
111
- <li v-for="(d, index3) in JSON.parse(String(detail.value))" :key="index3" class="item">
145
+ <ul
146
+ v-else-if="detail.id && detail.isArrayValue"
147
+ class="items"
148
+ >
149
+ <li
150
+ v-for="(d, index3) in JSON.parse(String(detail.value))"
151
+ :key="index3"
152
+ class="item"
153
+ >
112
154
  · {{ d }}
113
155
  </li>
114
156
  </ul>
@@ -20,7 +20,10 @@ const props = defineProps({
20
20
  :title="props.file.path"
21
21
  class="flex items-center hover:underline underline-offset-2 hover:underline-1"
22
22
  >
23
- <div i-system-uicons-document-justified class="text-blue-lightest dark:text-accent-light" />
23
+ <div
24
+ i-system-uicons-document-justified
25
+ class="text-blue-lightest dark:text-accent-light"
26
+ />
24
27
  <span>{{ props.file.name }}</span>
25
28
  </a>
26
29
  </li>
@@ -15,7 +15,10 @@ const props = withDefaults(
15
15
  </script>
16
16
 
17
17
  <template>
18
- <ul v-if="props.engines.length" class="engine-types">
18
+ <ul
19
+ v-if="props.engines.length"
20
+ class="engine-types"
21
+ >
19
22
  <li
20
23
  v-for="(engine, index) in props.engines"
21
24
  :key="engine.id"
@@ -1,16 +1,27 @@
1
1
  <template>
2
- <div class="product-link" itemscope itemtype="https://schema.org/Product">
2
+ <div
3
+ class="product-link"
4
+ itemscope
5
+ itemtype="https://schema.org/Product"
6
+ >
3
7
  <div
4
8
  :class="[bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel']"
5
9
  >
6
10
  <!-- Slot na ProductImage z Astro -->
7
11
  <slot name="image">
8
- <img src="/1x1.png" class="bg-neutral-lightest/70" :alt="productName" />
12
+ <img
13
+ src="/1x1.png"
14
+ class="bg-neutral-lightest/70"
15
+ :alt="productName"
16
+ >
9
17
  </slot>
10
18
  </div>
11
19
 
12
20
  <div :class="[bigTile ? '' : 'sm:pl-4']">
13
- <p v-if="price" class="block mb-2 font-600 font-headbold text-5">
21
+ <p
22
+ v-if="price"
23
+ class="block mb-2 font-600 font-headbold text-5"
24
+ >
14
25
  {{ price }}
15
26
  </p>
16
27
 
@@ -22,11 +33,20 @@
22
33
  v-html="nameFormatted"
23
34
  />
24
35
 
25
- <ProductNumber :product-number="productNumber" :copy-disabled="true" />
36
+ <ProductNumber
37
+ :product-number="productNumber"
38
+ :copy-disabled="true"
39
+ />
26
40
 
27
41
  <template v-if="index !== null">
28
- <meta itemprop="position" :content="index.toString()" />
29
- <meta itemprop="name" :content="nameFormatted" />
42
+ <meta
43
+ itemprop="position"
44
+ :content="index.toString()"
45
+ >
46
+ <meta
47
+ itemprop="name"
48
+ :content="nameFormatted"
49
+ >
30
50
  </template>
31
51
  </div>
32
52
  </div>
@@ -10,7 +10,10 @@ const props = defineProps({
10
10
  });
11
11
  </script>
12
12
  <template>
13
- <strong class="product-model" :data-pagefind-filter="`model:${props.carModel.name}`">{{
13
+ <strong
14
+ class="product-model"
15
+ :data-pagefind-filter="`model:${props.carModel.name}`"
16
+ >{{
14
17
  props.carModel.name
15
18
  }}</strong>
16
19
  </template>
@@ -11,8 +11,16 @@ const props = defineProps({
11
11
  </script>
12
12
 
13
13
  <template>
14
- <div inline-flex flex-wrap max-w-max>
15
- <span v-for="(modelId, index) in props.modelIds" :key="index" class="product-model block">
14
+ <div
15
+ inline-flex
16
+ flex-wrap
17
+ max-w-max
18
+ >
19
+ <span
20
+ v-for="(modelId, index) in props.modelIds"
21
+ :key="index"
22
+ class="product-model block"
23
+ >
16
24
  <ProductModel :id="modelId" />
17
25
  </span>
18
26
  </div>
@@ -16,7 +16,11 @@ const props = defineProps({
16
16
  </script>
17
17
 
18
18
  <template>
19
- <span v-for="position in props.positions" :key="position.sort" class="product-position">
19
+ <span
20
+ v-for="position in props.positions"
21
+ :key="position.sort"
22
+ class="product-position"
23
+ >
20
24
  {{ position.name }}
21
25
  </span>
22
26
  </template>
@@ -24,8 +24,15 @@ const settings = {
24
24
  </script>
25
25
 
26
26
  <template>
27
- <span v-for="(prcode, index) in settings.prcodes" :key="index" class="not-last:mr-1">
28
- <PrCode v-if="!String(prcode).includes('+')" :prcode="prcode" />
27
+ <span
28
+ v-for="(prcode, index) in settings.prcodes"
29
+ :key="index"
30
+ class="not-last:mr-1"
31
+ >
32
+ <PrCode
33
+ v-if="!String(prcode).includes('+')"
34
+ :prcode="prcode"
35
+ />
29
36
  <span v-else>
30
37
  <PrCode
31
38
  v-for="(splittedCode, index2) in String(prcode).split('+')"
@@ -23,7 +23,10 @@ const props = defineProps({
23
23
  </script>
24
24
 
25
25
  <template>
26
- <component :is="props.as" class="font-bold detail-name w-full sm:w-50 flex 2xl:w-64">
26
+ <component
27
+ :is="props.as"
28
+ class="font-bold detail-name w-full sm:w-50 flex 2xl:w-64"
29
+ >
27
30
  <span :class="styles && styles.length ? styles : 'mt-auto'">
28
31
  <b class="bg-white z-1 colon-after pr-1">{{ props.text }}</b>
29
32
  </span>
@@ -2,30 +2,18 @@
2
2
  import { PropType, computed } from 'vue';
3
3
  import ProductDetailName from './ProductDetailName.vue';
4
4
 
5
- interface ColorCode {
6
- code: string;
7
- name: string;
5
+ interface Link {
6
+ type: string;
7
+ url: string;
8
+ anchor: string;
8
9
  }
9
10
 
10
11
  interface TableItem {
11
12
  id: string;
12
- name: string;
13
- value: unknown; // Może być string, number, boolean, array (ColorCode[] lub string[])
14
- translated?: boolean;
15
- icon?: boolean;
16
- isArrayValue?: 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ą
21
- }
22
-
23
- interface GroupedLink {
24
- id: string;
25
- links: {
26
- name: string;
27
- value: string;
28
- }[];
13
+ label: string; // Display name from API
14
+ value: unknown; // Can be string, number, boolean, string array, or Link array
15
+ type?: string; // 'links' for link arrays
16
+ isGenericArray?: boolean; // for generic string arrays (e.g., position)
29
17
  }
30
18
 
31
19
  const props = defineProps({
@@ -33,21 +21,9 @@ const props = defineProps({
33
21
  caption: { type: String, default: null },
34
22
  });
35
23
 
36
- // Function to check if a value is a link
37
- const isLink = (id: string) => {
38
- return ['blog', 'youtube', 'vimeo'].includes(id);
39
- };
40
-
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
43
- const isColorArray = (item: TableItem) => {
44
- const colorIds = ['color', 'thread-color']; // lista ID które są kolorami
45
- return (item.isColorArray || colorIds.includes(item.id)) && Array.isArray(item.value);
46
- };
47
-
48
- // Function to check if it's paint marks (value is now a string from API)
49
- const isPaintMarks = (item: TableItem) => {
50
- return item.isPaintMarks && typeof item.value === 'string';
24
+ // Function to check if it's a links array from new API
25
+ const isLinksArray = (item: TableItem) => {
26
+ return item.type === 'links' && Array.isArray(item.value);
51
27
  };
52
28
 
53
29
  // Function to check if it's a generic array (e.g., for position)
@@ -55,33 +31,23 @@ const isGenericArray = (item: TableItem) => {
55
31
  return item.isGenericArray && Array.isArray(item.value);
56
32
  };
57
33
 
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
34
  // Function to check if value is HTML string (fallback)
64
35
  const isHtmlValue = (value: unknown): boolean => {
65
36
  return typeof value === 'string' && (value.includes('<span') || value.includes('<br>'));
66
37
  };
67
38
 
68
39
  // Function for specifying header text
69
- const getHeaderText = (row: TableItem | GroupedLink) => {
70
- if (row.id === 'blog') {
71
- return row.id.charAt(0).toUpperCase() + row.id.slice(1);
72
- }
73
- // Użyj `name` z obiektu `TableItem`, jeśli istnieje, w przeciwnym razie sformatuj `id`.
74
- return 'name' in row
75
- ? row.name
76
- : row.id
77
- .split('-')
78
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
79
- .join(' ');
40
+ const getHeaderText = (row: TableItem) => {
41
+ return row.label || row.id
42
+ .split('-')
43
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
44
+ .join(' ');
80
45
  };
81
46
 
82
47
  // Function to determine the icon class for a link type
83
- const getLinkIconClass = (linkId: string) => {
84
- switch (linkId) {
48
+ const getLinkIconClass = (linkType: string) => {
49
+ const type = linkType.toLowerCase();
50
+ switch (type) {
85
51
  case 'blog':
86
52
  return 'i-lucide-book-text';
87
53
  case 'youtube':
@@ -93,46 +59,13 @@ const getLinkIconClass = (linkId: string) => {
93
59
  }
94
60
  };
95
61
 
96
- // Grouping of elements by id
97
- const groupedItems = computed(() => {
98
- // ✅ Add validation to ensure props.items is an array
62
+ // Validate items
63
+ const validatedItems = computed(() => {
99
64
  if (!Array.isArray(props.items)) {
100
65
  console.warn('ProductDetailsList: items prop is not an array:', props.items);
101
66
  return [];
102
67
  }
103
-
104
- const result: (TableItem | GroupedLink)[] = [];
105
- const linkGroups = new Map<string, GroupedLink>();
106
-
107
- // Process all elements
108
- for (const item of props.items) {
109
- // If it's a link (blog, youtube, vimeo)
110
- if (isLink(item.id)) {
111
- // Add a link to the relevant group
112
- if (!linkGroups.has(item.id)) {
113
- linkGroups.set(item.id, {
114
- id: item.id,
115
- links: [],
116
- });
117
- }
118
-
119
- // Add link to the relevant group
120
- linkGroups.get(item.id)?.links.push({
121
- name: item.name,
122
- value: item.value as string,
123
- });
124
- } else {
125
- // If it's not a link, add it normally to the results
126
- result.push(item);
127
- }
128
- }
129
-
130
- // Add all link groups at the end
131
- for (const group of linkGroups.values()) {
132
- result.push(group);
133
- }
134
-
135
- return result;
68
+ return props.items;
136
69
  });
137
70
  </script>
138
71
 
@@ -144,74 +77,53 @@ const groupedItems = computed(() => {
144
77
  </slot>
145
78
  </caption>
146
79
  <colgroup>
147
- <col class="details-table-col" />
148
- <col class="details-table-col" />
80
+ <col class="details-table-col">
81
+ <col class="details-table-col">
149
82
  </colgroup>
150
83
  <tbody>
151
- <tr v-for="(row, index) in groupedItems" :key="index" class="details-table-row">
152
- <ProductDetailName as="th" :text="getHeaderText(row)" class="details-table-header" />
84
+ <tr
85
+ v-for="(row, index) in validatedItems"
86
+ :key="index"
87
+ class="details-table-row"
88
+ >
89
+ <ProductDetailName
90
+ as="th"
91
+ :text="getHeaderText(row)"
92
+ class="details-table-header"
93
+ />
153
94
 
154
- <td v-if="'links' in row" class="details-table-cell">
95
+ <td
96
+ v-if="isLinksArray(row)"
97
+ class="details-table-cell"
98
+ >
155
99
  <ul class="list-none p-0 m-0">
156
100
  <li
157
- v-for="(link, linkIndex) in row.links"
101
+ v-for="(link, linkIndex) in row.value as Link[]"
158
102
  :key="linkIndex"
159
103
  class="mb-2 last:mb-0 flex items-center"
160
104
  >
161
105
  <span
162
106
  :class="[
163
- getLinkIconClass(row.id),
107
+ getLinkIconClass(link.type),
164
108
  'leading-none inline-block mr-2 w-4 min-w-4 h-4 text-gray-400',
165
109
  ]"
166
110
  />
167
- <a :href="link.value" target="_blank" rel="noopener noreferrer" class="link-primary">
168
- {{ link.name }}
111
+ <a
112
+ :href="link.url"
113
+ target="_blank"
114
+ rel="noopener noreferrer"
115
+ class="link-primary"
116
+ >
117
+ {{ link.anchor }}
169
118
  </a>
170
119
  </li>
171
120
  </ul>
172
121
  </td>
173
122
 
174
- <td v-else-if="'id' in row && isColorArray(row)" class="details-table-cell">
175
- <ul class="list-none p-0 m-0">
176
- <li
177
- v-for="(colorItem, colorIndex) in row.value as ColorCode[]"
178
- :key="colorIndex"
179
- class="flex items-center gap-1 mb-1 last:mb-0"
180
- >
181
- <template v-if="colorItem.code">
182
- <code class="font-mono text-sm">
183
- {{ colorItem.code }}
184
- </code>
185
- <span class="text-gray-400">-</span>
186
- </template>
187
- <span class="text-gray-700 dark:text-gray-300">{{ colorItem.name }}</span>
188
- </li>
189
- </ul>
190
- </td>
191
-
192
- <td v-else-if="'id' in row && isPaintMarks(row)" class="details-table-cell">
193
- <span class="text-gray-700 dark:text-gray-300">{{ row.value }}</span>
194
- </td>
195
-
196
- <td v-else-if="'id' in row && isForExteriorColour(row)" class="details-table-cell">
197
- <ul class="list-none p-0 m-0">
198
- <li
199
- v-for="(colorEntry, colourIndex) in row.value as ColorCode[]"
200
- :key="colourIndex"
201
- class="flex items-center gap-1 mb-1 last:mb-0"
202
- >
203
- <template v-if="colorEntry.code">
204
- <code class="font-mono text-sm">
205
- {{ colorEntry.code }}
206
- </code>
207
- <span class="text-gray-400">-</span>
208
- </template>
209
- <span class="text-gray-700 dark:text-gray-300">{{ colorEntry.name }}</span>
210
- </li>
211
- </ul>
212
- </td>
213
-
214
- <td v-else-if="'id' in row && isGenericArray(row)" class="details-table-cell">
123
+ <td
124
+ v-else-if="isGenericArray(row)"
125
+ class="details-table-cell"
126
+ >
215
127
  <ul class="list-none p-0 m-0">
216
128
  <li
217
129
  v-for="(item, itemIndex) in row.value as string[]"
@@ -225,12 +137,14 @@ const groupedItems = computed(() => {
225
137
  </td>
226
138
 
227
139
  <td
228
- v-else-if="'id' in row && isHtmlValue(row.value)"
140
+ v-else-if="isHtmlValue(row.value)"
229
141
  class="details-table-cell"
230
142
  v-html="row.value"
231
143
  />
232
144
 
233
- <slot v-else-if="'id' in row" :name="row.id">
145
+ <slot
146
+ :name="row.id"
147
+ >
234
148
  <td class="details-table-cell">
235
149
  {{ row.value }}
236
150
  </td>
@@ -15,22 +15,24 @@ const toggleVisibility = () => {
15
15
  </script>
16
16
 
17
17
  <template>
18
- <div v-if="isShow" data-pagefind-ignore class="slimbanner">
18
+ <div
19
+ v-if="isShow"
20
+ data-pagefind-ignore
21
+ class="slimbanner"
22
+ >
19
23
  <span
20
24
  class="inline-block text-4xl w-6 h-3.5 min-w-[1.25rem] mr-3 bg-gradient-to-b stops-[#0057b7_50%,50%,#ffd700_100%]"
21
25
  />
22
- <span class="leading-none"
23
- ><span
24
- data-text="We stand with our friends and colleagues in Ukraine. To support Ukraine in their time of need visit "
25
- />
26
+ <span class="leading-none"><span
27
+ data-text="We stand with our friends and colleagues in Ukraine. To support Ukraine in their time of need visit "
28
+ />
26
29
  <a
27
30
  href="https://polo.blue/support-ukraine/"
28
31
  target="_blank"
29
32
  rel="noopener"
30
33
  title="Support Ukraine"
31
34
  class="underline underline-offset-2 hover:text-blue-wrc"
32
- >this page</a
33
- >.
35
+ >this page</a>.
34
36
  </span>
35
37
 
36
38
  <button
@@ -14,14 +14,26 @@ const capitalizeFirstLetter = (text: string) => {
14
14
  <table class="table-auto text-left border bg-white shadow-md">
15
15
  <thead class="bg-gray-500 text-white">
16
16
  <tr class="border">
17
- <th v-for="(thead, index) in theads" :key="index" class="px-4 py-2 font-semibold">
17
+ <th
18
+ v-for="(thead, index) in theads"
19
+ :key="index"
20
+ class="px-4 py-2 font-semibold"
21
+ >
18
22
  {{ capitalizeFirstLetter(thead) }}
19
23
  </th>
20
24
  </tr>
21
25
  </thead>
22
26
  <tbody>
23
- <tr v-for="(row, index) in props.data" :key="index" class="border">
24
- <td v-for="key in Object.keys(row)" :key="key" class="px-4 py-2">
27
+ <tr
28
+ v-for="(row, index) in props.data"
29
+ :key="index"
30
+ class="border"
31
+ >
32
+ <td
33
+ v-for="key in Object.keys(row)"
34
+ :key="key"
35
+ class="px-4 py-2"
36
+ >
25
37
  {{ row[key] }}
26
38
  </td>
27
39
  </tr>
@@ -18,7 +18,10 @@ const props = defineProps({
18
18
  </script>
19
19
 
20
20
  <template>
21
- <div v-if="props.translations !== null && props.translations.uri" data-pagefind-ignore>
21
+ <div
22
+ v-if="props.translations !== null && props.translations.uri"
23
+ data-pagefind-ignore
24
+ >
22
25
  <a
23
26
  aria-label="Change language"
24
27
  type="button"