spoko-design-system 1.27.2 → 1.28.0

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.
@@ -13,13 +13,13 @@
13
13
  "Bash(git diff:*)",
14
14
  "Bash(git log:*)",
15
15
  "Bash(git add:*)",
16
- "Bash(git commit:*)"
16
+ "Bash(git commit:*)",
17
17
  "Bash(git push:*)"
18
18
  ],
19
19
  "deny": [
20
20
  "Bash(pnpm semantic-release:*)",
21
21
  "Bash(pnpm publish:*)",
22
- "Bash(npm publish:*)",
22
+ "Bash(npm publish:*)"
23
23
  ],
24
24
  "ask": [
25
25
  "Bash(rm:*)",
@@ -26,7 +26,7 @@ jobs:
26
26
  actions: read
27
27
  steps:
28
28
  - name: Checkout repository
29
- uses: actions/checkout@v4
29
+ uses: actions/checkout@v6
30
30
  with:
31
31
  fetch-depth: 0
32
32
 
@@ -13,17 +13,17 @@ jobs:
13
13
 
14
14
  steps:
15
15
  - name: Checkout code
16
- uses: actions/checkout@v5
16
+ uses: actions/checkout@v6
17
17
 
18
18
  - name: Setup pnpm
19
19
  uses: pnpm/action-setup@v4
20
20
  with:
21
- version: 10.17.1
21
+ version: 10.30.3
22
22
 
23
23
  - name: Setup Node.js
24
- uses: actions/setup-node@v5
24
+ uses: actions/setup-node@v6
25
25
  with:
26
- node-version: '22'
26
+ node-version: '24'
27
27
  cache: 'pnpm'
28
28
 
29
29
  - name: Install dependencies
@@ -44,19 +44,19 @@ jobs:
44
44
 
45
45
  steps:
46
46
  - name: Checkout code
47
- uses: actions/checkout@v5
47
+ uses: actions/checkout@v6
48
48
  with:
49
49
  fetch-depth: 0 # Shallow clones should be disabled for better analysis
50
50
 
51
51
  - name: Setup pnpm
52
52
  uses: pnpm/action-setup@v4
53
53
  with:
54
- version: 10.17.1
54
+ version: 10.30.3
55
55
 
56
56
  - name: Setup Node.js
57
- uses: actions/setup-node@v5
57
+ uses: actions/setup-node@v6
58
58
  with:
59
- node-version: '22'
59
+ node-version: '24'
60
60
  cache: 'pnpm'
61
61
 
62
62
  - name: Install dependencies
@@ -24,9 +24,9 @@ jobs:
24
24
  runs-on: ubuntu-latest
25
25
  steps:
26
26
  - name: Checkout your repository using git
27
- uses: actions/checkout@v5
27
+ uses: actions/checkout@v6
28
28
  - name: Install, build, and upload your site
29
- uses: withastro/action@v4
29
+ uses: withastro/action@v5
30
30
  with:
31
31
  package-manager: pnpm@10.17.1
32
32
  # path: . # The root location of your Astro project inside the repository. (optional)
@@ -21,7 +21,7 @@ jobs:
21
21
 
22
22
  steps:
23
23
  - name: Checkout
24
- uses: actions/checkout@v5
24
+ uses: actions/checkout@v6
25
25
  with:
26
26
  fetch-depth: 0
27
27
  token: ${{ secrets.GITHUB_TOKEN }}
@@ -29,12 +29,12 @@ jobs:
29
29
  - name: Setup pnpm
30
30
  uses: pnpm/action-setup@v4
31
31
  with:
32
- version: 10.17.1
32
+ version: 10.30.3
33
33
 
34
34
  - name: Setup Node.js
35
- uses: actions/setup-node@v5
35
+ uses: actions/setup-node@v6
36
36
  with:
37
- node-version: 22
37
+ node-version: 24
38
38
  registry-url: 'https://registry.npmjs.org'
39
39
  cache: 'pnpm'
40
40
 
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [1.28.0](https://github.com/polo-blue/sds/compare/v1.27.3...v1.28.0) (2026-03-04)
2
+
3
+ ### Features
4
+
5
+ * **ProductDetailsList:** support individual link items in comprehensive ([459aae7](https://github.com/polo-blue/sds/commit/459aae745cc11c73ab4574cfa3d7f22f34ac7aed))
6
+
7
+ ## [1.27.3](https://github.com/polo-blue/sds/compare/v1.27.2...v1.27.3) (2026-03-04)
8
+
9
+ ### Bug Fixes
10
+
11
+ * **ButtonCopy:** prevent double-click race condition and View Transitions duplicate listeners ([3a3456d](https://github.com/polo-blue/sds/commit/3a3456d4a267330a2090801260ab0ccbea704a38))
12
+
1
13
  ## [1.27.2](https://github.com/polo-blue/sds/compare/v1.27.1...v1.27.2) (2026-03-03)
2
14
 
3
15
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoko-design-system",
3
- "version": "1.27.2",
3
+ "version": "1.28.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./index.ts",
@@ -142,7 +142,7 @@
142
142
  "unocss": "^0.65.0",
143
143
  "vite": "^7.3.1"
144
144
  },
145
- "packageManager": "pnpm@10.17.1",
145
+ "packageManager": "pnpm@10.30.3",
146
146
  "pnpm": {
147
147
  "default": "9.15.3",
148
148
  "overrides": {
@@ -33,12 +33,11 @@ const COPY_ICON = `url("data:image/svg+xml;utf8,${encodeURIComponent(
33
33
  class ClipboardButton {
34
34
  private static readonly COPY_TIMEOUT = 2000;
35
35
  private static readonly ANALYTICS_EVENT = 'product_code_copy';
36
+ private readonly originalText: string;
37
+ private resetTimer: ReturnType<typeof setTimeout> | null = null;
36
38
 
37
39
  constructor(private button: HTMLButtonElement) {
38
- this.init();
39
- }
40
-
41
- private init(): void {
40
+ this.originalText = this.tooltip?.dataset.text || 'Copy';
42
41
  this.button.addEventListener('click', () => this.handleCopy());
43
42
  }
44
43
 
@@ -54,10 +53,6 @@ const COPY_ICON = `url("data:image/svg+xml;utf8,${encodeURIComponent(
54
53
  return this.button.dataset.category || '';
55
54
  }
56
55
 
57
- private get originalText(): string {
58
- return this.tooltip.dataset.text || 'Copy';
59
- }
60
-
61
56
  private get copiedText(): string {
62
57
  return this.tooltip.dataset.copiedText || 'Copied';
63
58
  }
@@ -93,9 +88,11 @@ const COPY_ICON = `url("data:image/svg+xml;utf8,${encodeURIComponent(
93
88
  }
94
89
 
95
90
  private updateTooltip(): void {
91
+ if (this.resetTimer) clearTimeout(this.resetTimer);
96
92
  this.tooltip.dataset.text = this.copiedText;
97
- setTimeout(() => {
93
+ this.resetTimer = setTimeout(() => {
98
94
  this.tooltip.dataset.text = this.originalText;
95
+ this.resetTimer = null;
99
96
  }, ClipboardButton.COPY_TIMEOUT);
100
97
  }
101
98
 
@@ -118,10 +115,11 @@ const COPY_ICON = `url("data:image/svg+xml;utf8,${encodeURIComponent(
118
115
  }
119
116
  }
120
117
 
121
- // Initialize copy buttons on page load
118
+ // Initialize copy buttons on page load (skip already-initialized for View Transitions)
122
119
  document.addEventListener('astro:page-load', () => {
123
120
  document.querySelectorAll('.btn-copy').forEach(button => {
124
- if (button instanceof HTMLButtonElement) {
121
+ if (button instanceof HTMLButtonElement && !button.dataset.copyInit) {
122
+ button.dataset.copyInit = '1';
125
123
  new ClipboardButton(button);
126
124
  }
127
125
  });
@@ -10,7 +10,8 @@ interface Link {
10
10
 
11
11
  interface TableItem {
12
12
  id: string;
13
- label: string; // Display name from API
13
+ label?: string; // Display name from API
14
+ name?: string; // Alternative display name (used by individual link items)
14
15
  value: unknown; // Can be string, number, boolean, string array, or Link array
15
16
  type?: string; // 'links' for link arrays
16
17
  isGenericArray?: boolean; // for generic string arrays (e.g., position)
@@ -21,11 +22,17 @@ const props = defineProps({
21
22
  caption: { type: String, default: null },
22
23
  });
23
24
 
24
- // Function to check if it's a links array from new API
25
+ // Function to check if it's a links array (legacy grouped format)
25
26
  const isLinksArray = (item: TableItem) => {
26
27
  return item.type === 'links' && Array.isArray(item.value);
27
28
  };
28
29
 
30
+ // Function to check if it's an individual link item
31
+ // Backend sends: { id: 'blog', name: 'anchor', value: 'https://...', type: 'link' }
32
+ const isIndividualLink = (item: TableItem) => {
33
+ return item.type === 'link' && typeof item.value === 'string';
34
+ };
35
+
29
36
  // Function to check if it's a generic array (e.g., for position)
30
37
  const isGenericArray = (item: TableItem) => {
31
38
  return item.isGenericArray && Array.isArray(item.value);
@@ -108,6 +115,21 @@ const validatedItems = computed(() => {
108
115
  </ul>
109
116
  </td>
110
117
 
118
+ <!-- Individual Link (flat format: id=blog/youtube/vimeo, value=url, name=anchor) -->
119
+ <td v-else-if="isIndividualLink(row)" class="details-table-cell">
120
+ <div class="flex items-center">
121
+ <span
122
+ :class="[
123
+ getLinkIconClass(row.id),
124
+ 'leading-none inline-block mr-2 w-4 min-w-4 h-4 text-gray-400',
125
+ ]"
126
+ />
127
+ <a :href="row.value as string" target="_blank" rel="noopener noreferrer" class="link-primary">
128
+ {{ row.name || row.label || row.id }}
129
+ </a>
130
+ </div>
131
+ </td>
132
+
111
133
  <!-- Generic String Array -->
112
134
  <td v-else-if="isGenericArray(row)" class="details-table-cell">
113
135
  <ul class="list-none p-0 m-0">