@cyber-harbour/ui 2.2.35 → 3.0.0-fix-ci-double-publish.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.
Files changed (75) hide show
  1. package/README.md +117 -202
  2. package/bin/switch-ui-lib.js +54 -26
  3. package/dist/Core/IconComponents/index.d.mts +165 -0
  4. package/dist/Core/IconComponents/index.d.ts +165 -0
  5. package/dist/Core/IconComponents/index.js +2 -0
  6. package/dist/Core/IconComponents/index.js.map +1 -0
  7. package/dist/Core/IconComponents/index.mjs +2 -0
  8. package/dist/Core/IconComponents/index.mjs.map +1 -0
  9. package/dist/Icons2/index.d.mts +396 -0
  10. package/dist/Icons2/index.d.ts +396 -0
  11. package/dist/Icons2/index.js +2 -0
  12. package/dist/Icons2/index.js.map +1 -0
  13. package/dist/Icons2/index.mjs +2 -0
  14. package/dist/Icons2/index.mjs.map +1 -0
  15. package/dist/PdfDriver-P5ADXPSY.mjs +2 -0
  16. package/dist/PdfDriver-P5ADXPSY.mjs.map +1 -0
  17. package/dist/PdfDriver-TMPVSYW4.js +2 -0
  18. package/dist/PdfDriver-TMPVSYW4.js.map +1 -0
  19. package/dist/chunk-2RPPHDGW.mjs +2 -0
  20. package/dist/chunk-2RPPHDGW.mjs.map +1 -0
  21. package/dist/chunk-3UCQYQQT.js +2 -0
  22. package/dist/chunk-3UCQYQQT.js.map +1 -0
  23. package/dist/chunk-6YUK4MG2.js +3 -0
  24. package/dist/chunk-6YUK4MG2.js.map +1 -0
  25. package/dist/chunk-7LHQWEWV.mjs +2 -0
  26. package/dist/chunk-7LHQWEWV.mjs.map +1 -0
  27. package/dist/chunk-AYDF3IFZ.js +2 -0
  28. package/dist/chunk-AYDF3IFZ.js.map +1 -0
  29. package/dist/chunk-EKYQRECJ.mjs +3 -0
  30. package/dist/chunk-EKYQRECJ.mjs.map +1 -0
  31. package/dist/chunk-HYLHDKBT.mjs +3 -0
  32. package/dist/chunk-HYLHDKBT.mjs.map +1 -0
  33. package/dist/chunk-IBAON32O.mjs +3 -0
  34. package/dist/chunk-IBAON32O.mjs.map +1 -0
  35. package/dist/chunk-JOQGNYHN.js +3 -0
  36. package/dist/chunk-JOQGNYHN.js.map +1 -0
  37. package/dist/chunk-NQZUCXJV.js +2 -0
  38. package/dist/chunk-NQZUCXJV.js.map +1 -0
  39. package/dist/chunk-QWPVIX2T.mjs +2 -0
  40. package/dist/chunk-QWPVIX2T.mjs.map +1 -0
  41. package/dist/chunk-RYHWWDCM.mjs +2 -0
  42. package/dist/chunk-RYHWWDCM.mjs.map +1 -0
  43. package/dist/chunk-SRPPNCDM.js +2 -0
  44. package/dist/chunk-SRPPNCDM.js.map +1 -0
  45. package/dist/chunk-XR7P7DQC.js +3 -0
  46. package/dist/chunk-XR7P7DQC.js.map +1 -0
  47. package/dist/index.d.mts +1804 -1881
  48. package/dist/index.d.ts +1804 -1881
  49. package/dist/index.js +7 -297
  50. package/dist/index.js.map +1 -1
  51. package/dist/index.mjs +7 -297
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/styles/tailwind.css +587 -3
  54. package/dist/utils/index.d.mts +7 -0
  55. package/dist/utils/index.d.ts +7 -0
  56. package/dist/utils/index.js +2 -0
  57. package/dist/utils/index.js.map +1 -0
  58. package/dist/utils/index.mjs +2 -0
  59. package/dist/utils/index.mjs.map +1 -0
  60. package/dist/utils-BGHa_rUP.d.mts +26 -0
  61. package/dist/utils-BGHa_rUP.d.ts +26 -0
  62. package/package.json +69 -50
  63. package/dist/PdfDriver-D37B42JP.mjs +0 -2
  64. package/dist/PdfDriver-D37B42JP.mjs.map +0 -1
  65. package/dist/PdfDriver-WICDQXHI.js +0 -2
  66. package/dist/PdfDriver-WICDQXHI.js.map +0 -1
  67. package/dist/chunk-JRNFYOX5.mjs +0 -1394
  68. package/dist/chunk-JRNFYOX5.mjs.map +0 -1
  69. package/dist/chunk-XLDJPZWO.js +0 -1394
  70. package/dist/chunk-XLDJPZWO.js.map +0 -1
  71. package/dist/index.css +0 -3
  72. package/dist/index.css.map +0 -1
  73. package/dist/styles/tailwind.css.map +0 -1
  74. package/dist/styles/tailwind.d.mts +0 -2
  75. package/dist/styles/tailwind.d.ts +0 -2
package/README.md CHANGED
@@ -1,301 +1,216 @@
1
- # Початок роботи з Cyber Harbor UI Kit
1
+ # Cyber Harbour UI Kit
2
2
 
3
- ## Розробка
3
+ React UI component library built with Tailwind CSS 4, class-variance-authority, and Lucide icons.
4
4
 
5
- ### Встановлення
5
+ ## Installation
6
6
 
7
7
  ```bash
8
- npm install
8
+ npm install @cyber-harbour/ui
9
9
  ```
10
10
 
11
- ### Збірка бібліотеки
12
-
13
- Бібліотека збирається за допомогою tsup, що забезпечує оптимізовані збірки для форматів ESM та CommonJS.
11
+ ### Peer dependencies
14
12
 
15
13
  ```bash
16
- # Розробка з режимом відстеження
17
- npm run dev
18
-
19
- # Продакшн збірка
20
- npm run build
21
-
22
- # Збірка без мінімізації
23
- npm run build:dev
24
-
25
- # Перевірка типів без збірки
26
- npm run type-check
14
+ npm install tailwindcss react-tiny-popover
27
15
  ```
28
16
 
29
- ### Результат збірки
17
+ FileViewer additionally requires: `react-pdf`, `d3`, `date-fns`, `@codemirror/lang-*`, `@uiw/react-codemirror`.
30
18
 
31
- При збірці бібліотеки в папці `dist` генерується наступне:
19
+ ## Usage
32
20
 
33
- - ESM модулі (`.mjs` файли)
34
- - CommonJS модулі (`.js` файли)
35
- - TypeScript файли декларацій (`.d.ts` та `.d.mts`)
36
- - Source maps
21
+ ### Import styles
37
22
 
38
- ### Storybook
23
+ The library exports source Tailwind CSS (with `@theme` tokens, not compiled output). Your project must have its own Tailwind CSS 4 pipeline to compile it.
39
24
 
40
- Ви можете запустити Storybook для розробки та тестування компонентів:
25
+ See [Vite SPA](#vite-spa-react) or [Next.js](#nextjs) setup sections below for full configuration.
41
26
 
42
- ```bash
43
- npm run storybook
44
- ```
45
-
46
- Для збірки Storybook:
27
+ ### Import components
47
28
 
48
- ```bash
49
- npm run build-storybook
29
+ ```tsx
30
+ import { Button, Alert, Box, Input } from '@cyber-harbour/ui';
31
+ import { SearchIcon, ChevronDownIcon } from '@cyber-harbour/ui/Icons';
32
+ import { cn, useEscapeLayer, useOutclickLayer } from '@cyber-harbour/ui/utils';
50
33
  ```
51
34
 
52
- ## Оптимізації збірки
53
-
54
- Проект використовує різні оптимізації для ефективної збірки:
55
-
56
- ### Продакшн режим
57
-
58
- - Мінімізація вихідних файлів
59
- - Tree shaking для видалення невикористаного коду
60
- - Видалення console logs
61
- - Source maps для налагодження
62
-
63
- ### Режим розробки
64
-
65
- - Режим відстеження для автоматичної перебудови при змінах
66
- - Вбудовані source maps для легшого налагодження
67
- - Без мінімізації для швидшої збірки
68
- - Без генерації типів для швидкості
35
+ | Subpath | Contents |
36
+ |---|---|
37
+ | `@cyber-harbour/ui` | Components |
38
+ | `@cyber-harbour/ui/Icons` | Icons (Lucide re-exports) |
39
+ | `@cyber-harbour/ui/utils` | `cn`, hooks, `getFilesFromDataTransfer` |
40
+ | `@cyber-harbour/ui/styles` | Source Tailwind CSS with custom theme (requires consumer Tailwind pipeline) |
69
41
 
70
- ## Інструмент перемикання UI бібліотеки
42
+ ## Development
71
43
 
72
- Цей інструмент дозволяє легко перемикатися між локальною версією UI бібліотеки та версією з NPM.
73
-
74
- ### Використання
75
-
76
- #### Варіант 1: Через npx (рекомендований)
44
+ ### Setup
77
45
 
78
46
  ```bash
79
- npx @cyber-harbour/ui switch-ui-lib
80
- ```
81
-
82
- #### Варіант 2: Через npm скрипт
83
-
84
- Додайте скрипт в package.json вашого проекту:
85
-
86
- ```json
87
- {
88
- "scripts": {
89
- "switch-ui": "npx @cyber-harbour/ui switch-ui-lib"
90
- }
91
- }
47
+ npm install
92
48
  ```
93
49
 
94
- Потім запускайте:
50
+ ### Scripts
95
51
 
96
52
  ```bash
97
- npm run switch-ui
53
+ npm run dev # Watch mode
54
+ npm run build # Production build
55
+ npm run build:dev # Dev build (no minification)
56
+ npm run type:check # Type check
57
+ npm run test # Run tests
58
+ npm run storybook # Start Storybook
59
+ npm run build-storybook
98
60
  ```
99
61
 
100
- ### Налаштування
62
+ ### Build output
101
63
 
102
- #### Змінні середовища
64
+ The `dist` folder contains:
103
65
 
104
- Створіть файл `.env` або `.env.local` в корені вашого проекту:
66
+ - ESM modules (`.mjs`)
67
+ - CommonJS modules (`.js`)
68
+ - TypeScript declarations (`.d.ts`, `.d.mts`)
69
+ - Source maps
105
70
 
106
- ```bash
107
- UI_LIBRARY_PATH=/path/to/your/ui-kit
108
- ```
71
+ ## Integration
109
72
 
110
- Якщо змінна не встановлена, скрипт спробує знайти UI бібліотеку в папці `ui-kit` поруч з вашим проектом.
73
+ The library uses **Tailwind CSS 4** with CSS-based configuration. Styles are shipped as a prebuilt CSS file with custom color palette, shadows, and z-index tokens.
111
74
 
112
- #### Структура проектів
75
+ ### Dark mode
113
76
 
114
- Рекомендована структура:
77
+ Dark mode uses the `dark` CSS class. Add `class="dark"` to a parent element:
115
78
 
79
+ ```html
80
+ <html class="dark">
116
81
  ```
117
- projects/
118
- ├── ui-kit/ # UI бібліотека
119
- ├── my-app/ # Ваш проект
120
- └── another-app/ # Інший проект
121
- ```
122
-
123
- ### Що робить скрипт
124
-
125
- #### Локальна версія
126
-
127
- - Видаляє NPM версію пакету
128
- - Створює npm link для React та React DOM
129
- - Створює глобальний link для UI бібліотеки
130
- - Підключає локальну версію через npm link
131
-
132
- #### NPM версія
133
-
134
- - Видаляє всі npm links
135
- - Встановлює останню версію з NPM
136
-
137
- ### Залежності
138
82
 
139
- Скрипт потребує:
83
+ Components automatically adapt to dark mode.
140
84
 
141
- - `prompts` - для інтерактивного вибору
142
- - `dotenv` - для читання змінних середовища (опційно)
85
+ ### Vite SPA (React)
143
86
 
144
- Ці пакети автоматично встановлюються разом з UI бібліотекою.
145
-
146
- ### Усунення несправностей
147
-
148
- Відсутній лінк на бібліотеку після першого завантаження. Запустіть
87
+ 1. Install dependencies:
149
88
 
150
89
  ```bash
151
- npm link
90
+ npm install @tailwindcss/vite tailwindcss
152
91
  ```
153
92
 
154
- ---
155
-
156
- # 🔹 Інструкція інтеграції UI-kit у Next.js з Tailwind
93
+ 2. Add the Tailwind plugin to `vite.config.ts`:
157
94
 
158
- Цей UI-kit побудований на **TailwindCSS** і постачається з власною конфігурацією (`tailwind.config.js`).
159
- Щоб уникнути конфліктів і дозволити кастомізацію у проєкті, потрібно **мерджити** конфіг UI-kit із конфігом Next.js.
95
+ ```ts
96
+ import tailwindcss from '@tailwindcss/vite';
97
+ import { defineConfig } from 'vite';
98
+ import react from '@vitejs/plugin-react';
160
99
 
161
- ---
100
+ export default defineConfig({
101
+ plugins: [react(), tailwindcss()],
102
+ });
103
+ ```
162
104
 
163
- ## 1. Встановіть залежності
105
+ 3. Import library styles in your global CSS (`src/index.css`):
164
106
 
165
- У вашому Next.js-проєкті мають бути встановлені:
107
+ ```css
108
+ @import 'tailwindcss';
109
+ @import '@cyber-harbour/ui/styles';
166
110
 
167
- ```bash
168
- pnpm add tailwindcss postcss autoprefixer
111
+ @source "../node_modules/@cyber-harbour/ui/dist";
169
112
  ```
170
113
 
171
- ---
172
-
173
- ## 2. Створіть `tailwind.config.js` у Next.js
114
+ ### Next.js
174
115
 
175
- У корені вашого Next.js-проєкту створіть файл `tailwind.config.js` і підключіть конфіг із UI-kit.
176
- Ми будемо мерджити конфіги за допомогою `lodash.merge`:
116
+ 1. Install dependencies:
177
117
 
178
118
  ```bash
179
- pnpm add lodash.merge
119
+ npm install @tailwindcss/postcss tailwindcss
180
120
  ```
181
121
 
182
- **`tailwind.config.js`**
122
+ 2. Configure PostCSS in `postcss.config.mjs`:
183
123
 
184
124
  ```js
185
- const merge = require('lodash.merge');
186
- const uiKitConfig = require('ui-kit/tailwind.config.js'); // шлях до UI-kit пакета
187
-
188
- module.exports = merge({}, uiKitConfig, {
189
- content: [
190
- './pages/**/*.{js,ts,jsx,tsx}',
191
- './components/**/*.{js,ts,tsx}',
192
- './app/**/*.{js,ts,jsx,tsx}', // якщо використовуєте app router
193
- './node_modules/@cyber-harbour/ui/dist/**/*.{js,mjs', // важливо: UI-kit компоненти
194
- ],
195
- theme: {
196
- extend: {
197
- colors: {
198
- accent: '#f59e0b', // локальні кольори вашого проєкту
199
- },
200
- },
125
+ export default {
126
+ plugins: {
127
+ '@tailwindcss/postcss': {},
201
128
  },
202
- });
129
+ };
203
130
  ```
204
131
 
205
- ---
206
-
207
- ## 3. Підключіть Tailwind у глобальні стилі
208
-
209
- У вашому Next.js проєкті додайте у `globals.css` (або `app/globals.css`):
132
+ 3. Import library styles in your global CSS (`app/globals.css`):
210
133
 
211
134
  ```css
212
- @tailwind base;
213
- @tailwind components;
214
- @tailwind utilities;
215
- ```
216
-
217
- ---
135
+ @import 'tailwindcss';
136
+ @import '@cyber-harbour/ui/styles';
218
137
 
219
- ## 4. Використання компонентів із UI-kit
138
+ @source "../node_modules/@cyber-harbour/ui/dist";
139
+ ```
220
140
 
221
- Тепер ви можете імпортувати і використовувати компоненти з UI-kit у будь-яких файлах вашого Next.js-проєкту:
141
+ ### Example
222
142
 
223
143
  ```tsx
224
- import { Button } from 'ui-kit';
144
+ import { Button, Alert } from '@cyber-harbour/ui';
145
+ import { SearchIcon } from '@cyber-harbour/ui/Icons';
225
146
 
226
147
  export default function Page() {
227
148
  return (
228
149
  <div className="p-6">
229
- <Button variant="primary">Клікни мене</Button>
150
+ <Alert color="success">Operation completed</Alert>
151
+ <Button color="primary" icon={<SearchIcon />}>
152
+ Search
153
+ </Button>
230
154
  </div>
231
155
  );
232
156
  }
233
157
  ```
234
158
 
235
- ---
236
-
237
- ## 5. Кастомізація теми
159
+ ## FileViewer configuration
238
160
 
239
- Якщо потрібно змінити кольори, spacing чи інші токени —
240
- додавайте їх у секцію `theme.extend` вашого `tailwind.config.js`.
161
+ PDF preview requires copying the pdfjs-dist worker.
241
162
 
242
- ⚡️ Вони автоматично поєднаються з токенами з UI-kit.
163
+ ### Auto copy
243
164
 
244
- ---
165
+ Add the command to your `postinstall` script in `package.json` so the worker is copied automatically after every install:
245
166
 
246
- ## 6. Альтернатива підключення
247
-
248
- Додайте до вашого головного CSS файлу або entry point:
249
-
250
- ```css
251
- /* Імпорт скомпільованих Tailwind стилів з бібліотеки */
252
- @import '@cyber-harbour/ui/styles';
167
+ ```json
168
+ {
169
+ "scripts": {
170
+ "postinstall": "npx @cyber-harbour/ui copy-pdfjs"
171
+ }
172
+ }
253
173
  ```
254
174
 
255
- Або в JS/TS файлі:
175
+ Or run it manually:
256
176
 
257
- ```js
258
- import '@cyber-harbour/ui/styles';
177
+ ```bash
178
+ npx @cyber-harbour/ui copy-pdfjs
259
179
  ```
260
180
 
261
- ---
262
-
263
- ## 7. FileViewer configuration
264
-
265
- Для роботи перегляду PDF потрібно скопіювати worker pdfjs-dist
266
-
267
- ### Автоматичне копіювання
181
+ ### Custom worker directory
268
182
 
269
183
  ```bash
270
- npx @cyber-harbour/ui copy-pdfjs
184
+ UI_LIBRARY_WORKERS_DIR=public/assets npx @cyber-harbour/ui copy-pdfjs
271
185
  ```
272
186
 
273
- ### Кастомна папка для worker'ів
187
+ ## Switch UI library tool
188
+
189
+ Switch between local and NPM versions of the library during development.
274
190
 
275
191
  ```bash
276
- UI_LIBRARY_WORKERS_DIR=public/assets npx @cyber-harbour/ui copy-pdfjs
192
+ npx @cyber-harbour/ui switch-ui-lib
277
193
  ```
278
194
 
279
- ### Вирішення проблем
195
+ ### Setup
280
196
 
281
- Якщо виникає помилка про відсутність PDF worker'а:
197
+ Set the path to your local UI kit via `.env` or `.env.local`:
282
198
 
283
- 1. **Встановіть pdfjs-dist** у вашому проекті:
199
+ ```bash
200
+ UI_LIBRARY_PATH=/path/to/your/ui-kit
201
+ ```
284
202
 
285
- ```bash
286
- npm install pdfjs-dist
287
- ```
203
+ If not set, the script looks for `ui-kit` folder next to your project.
288
204
 
289
- 2. **Або встановіть як peer dependency** та запустіть скрипт:
205
+ ### Recommended project structure
290
206
 
291
- ```bash
292
- npm install --save-peer pdfjs-dist
293
- npx @cyber-harbour/ui copy-pdfjs
294
- ```
207
+ ```
208
+ projects/
209
+ ui-kit/ # This library
210
+ my-app/ # Your project
211
+ another-app/ # Another project
212
+ ```
295
213
 
296
- 3. **Перевірте структуру проекту**: скрипт шукає worker у наступних місцях:
297
- - `node_modules/pdfjs-dist/build/pdf.worker.min.mjs`
298
- - `node_modules/@cyber-harbour/ui/node_modules/pdfjs-dist/build/pdf.worker.min.mjs`
299
- - Інші можливі локації
214
+ ## Migration
300
215
 
301
- Скрипт автоматично знайде правильну локацію та скопіює worker до папки `public/workers/`.
216
+ See [MIGRATION.md](MIGRATION.md) for breaking changes when upgrading from v1 to v3.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const prompts = require('prompts');
4
- const { execSync } = require('child_process');
4
+ const { execSync, execFileSync } = require('child_process');
5
5
  const path = require('path');
6
6
  const fs = require('fs');
7
7
 
@@ -57,15 +57,6 @@ function isUsingLocalVersion() {
57
57
  }
58
58
  }
59
59
 
60
- function isUsingNpmVersion() {
61
- try {
62
- const realPath = fs.realpathSync(pkgPath);
63
- return !realPath.includes('..') && realPath.includes('node_modules');
64
- } catch {
65
- return false;
66
- }
67
- }
68
-
69
60
  function checkLocalPathExists() {
70
61
  if (!fs.existsSync(localPath)) {
71
62
  console.log(`⚠️ Локальний шлях не знайдено: ${localPath}`);
@@ -148,29 +139,66 @@ async function main() {
148
139
  }
149
140
 
150
141
  if (mode === 'npm') {
151
- const versionResponse = await prompts({
152
- type: 'text',
153
- name: 'version',
154
- message: 'Введіть версію або тег (latest, next, 2.0.0, alpha, beta):',
155
- initial: 'latest',
156
- validate: value => value.length > 0 ? true : 'Версія не може бути пустою'
142
+ let distTags = {};
143
+ try {
144
+ const raw = execFileSync('npm', ['view', packageName, 'dist-tags', '--json'], {
145
+ stdio: ['ignore', 'pipe', 'ignore'],
146
+ }).toString();
147
+ distTags = JSON.parse(raw);
148
+ } catch {
149
+ console.log('⚠️ Не вдалося отримати список тегів з npm — буде запропоновано ручний ввід.');
150
+ }
151
+
152
+ const PRIMARY_TAGS = ['latest', 'next', 'next-gen', 'beta', 'alpha', 'dev'];
153
+ const tagEntries = Object.entries(distTags).sort(([a], [b]) => {
154
+ const ai = PRIMARY_TAGS.indexOf(a);
155
+ const bi = PRIMARY_TAGS.indexOf(b);
156
+ if (ai !== -1 || bi !== -1) return (ai === -1 ? Infinity : ai) - (bi === -1 ? Infinity : bi);
157
+ return a.localeCompare(b);
157
158
  });
158
-
159
- if (!versionResponse.version) {
159
+ const tagChoices = tagEntries.map(([tag, version]) => ({
160
+ title: `${tag} (${version})`,
161
+ value: tag,
162
+ }));
163
+
164
+ const latestIdx = tagChoices.findIndex(c => c.value === 'latest');
165
+
166
+ const { selected } = await prompts({
167
+ type: 'select',
168
+ name: 'selected',
169
+ message: 'Оберіть тег або вкажіть власну версію:',
170
+ choices: [
171
+ ...tagChoices,
172
+ { title: '✏️ Ввести версію або тег вручну', value: '__custom__' },
173
+ ],
174
+ initial: latestIdx >= 0 ? latestIdx : 0,
175
+ });
176
+
177
+ if (!selected) {
160
178
  console.log('❌ Операція скасована.');
161
179
  return;
162
180
  }
163
-
164
- const version = versionResponse.version.startsWith('@')
165
- ? versionResponse.version.substring(1)
166
- : versionResponse.version;
167
- const packageToInstall = `${packageName}@${version}`;
168
181
 
169
- if (isUsingNpmVersion()) {
170
- console.log('✅ Вже використовується версія з NPM.');
171
- return;
182
+ let version = selected;
183
+ if (selected === '__custom__') {
184
+ const { custom } = await prompts({
185
+ type: 'text',
186
+ name: 'custom',
187
+ message: 'Введіть версію або тег:',
188
+ initial: 'latest',
189
+ validate: value => (value.length > 0 ? true : 'Версія не може бути пустою'),
190
+ });
191
+
192
+ if (!custom) {
193
+ console.log('❌ Операція скасована.');
194
+ return;
195
+ }
196
+
197
+ version = custom.startsWith('@') ? custom.substring(1) : custom;
172
198
  }
173
199
 
200
+ const packageToInstall = `${packageName}@${version}`;
201
+
174
202
  try {
175
203
  // Видаляємо лінк якщо він існує
176
204
  console.log('🔄 Видаляємо лінки...');