@yartsun/chat-widget-types 1.0.15 → 1.0.17

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 (43) hide show
  1. package/README.md +20 -0
  2. package/dist/config.types.d.ts +46 -9
  3. package/dist/config.types.d.ts.map +1 -1
  4. package/dist/default-config.d.ts +1 -1
  5. package/dist/default-config.d.ts.map +1 -1
  6. package/dist/default-config.js +2 -319
  7. package/dist/default-config.js.map +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/migration/commands.d.ts +1 -0
  11. package/dist/migration/commands.d.ts.map +1 -1
  12. package/dist/migration/commands.js +58 -2
  13. package/dist/migration/commands.js.map +1 -1
  14. package/dist/migration/examples.d.ts +1 -1
  15. package/dist/migration/facade.d.ts +8 -0
  16. package/dist/migration/facade.d.ts.map +1 -1
  17. package/dist/migration/facade.js +22 -2
  18. package/dist/migration/facade.js.map +1 -1
  19. package/dist/migration/migrator.d.ts +1 -0
  20. package/dist/migration/migrator.d.ts.map +1 -1
  21. package/dist/migration/migrator.js +23 -4
  22. package/dist/migration/migrator.js.map +1 -1
  23. package/dist/migration/strategies.d.ts +52 -0
  24. package/dist/migration/strategies.d.ts.map +1 -1
  25. package/dist/migration/strategies.js +277 -4
  26. package/dist/migration/strategies.js.map +1 -1
  27. package/dist/migration/types.d.ts +9 -1
  28. package/dist/migration/types.d.ts.map +1 -1
  29. package/dist/migration/types.js +7 -1
  30. package/dist/migration/types.js.map +1 -1
  31. package/package.json +25 -2
  32. package/src/config.types.ts +50 -10
  33. package/src/default-config.ts +3 -329
  34. package/src/index.ts +5 -3
  35. package/src/migration/commands.ts +65 -2
  36. package/src/migration/facade.ts +23 -2
  37. package/src/migration/migrator.ts +22 -6
  38. package/src/migration/strategies.ts +291 -4
  39. package/src/migration/types.ts +11 -1
  40. package/themes/configV3-shine.json +369 -0
  41. package/themes/configV3-soft.json +369 -0
  42. package/themes/configV3-ultra.json +369 -0
  43. package/themes/configV3.json +370 -0
@@ -231,11 +231,298 @@ export const V1_TO_V2_STRATEGIES: MigrationStrategy[] = [
231
231
  new AddBottomElementsV1toV2Strategy()
232
232
  ]
233
233
 
234
+ /** Стратегия добавления theme и container в settings для V2->V3 */
235
+ export class AddThemeAndContainerV2toV3Strategy extends BaseMigrationStrategy {
236
+ name = 'AddThemeAndContainerV2toV3'
237
+ description = 'Adds theme and container (innerBorder, outerBorder, gradient) to settings'
238
+ appliesTo = { from: '2.0' as const, to: '3.0' as const }
239
+
240
+ apply(context: MigrationContext): MigrationStepResult {
241
+ try {
242
+ const config = { ...context.config }
243
+ const warnings: string[] = []
244
+
245
+ // Добавляем theme если его нет
246
+ if (!config.settings.theme) {
247
+ config.settings.theme = DEFAULT_CONFIG.settings.theme // 'auto'
248
+ warnings.push(`Добавлено поле theme: '${config.settings.theme}'`)
249
+ }
250
+
251
+ // Добавляем container если его нет
252
+ if (!config.settings.container) {
253
+ config.settings.container = {
254
+ innerBorder: {
255
+ width: DEFAULT_CONFIG.settings.container?.innerBorder?.width || 0,
256
+ color: DEFAULT_CONFIG.settings.container?.innerBorder?.color || 'transparent',
257
+ style: DEFAULT_CONFIG.settings.container?.innerBorder?.style || 'solid',
258
+ },
259
+ outerBorder: {
260
+ width: DEFAULT_CONFIG.settings.container?.outerBorder?.width || 0,
261
+ color: DEFAULT_CONFIG.settings.container?.outerBorder?.color || 'transparent',
262
+ style: DEFAULT_CONFIG.settings.container?.outerBorder?.style || 'solid',
263
+ },
264
+ gradient: DEFAULT_CONFIG.settings.container?.gradient || 'transparent',
265
+ }
266
+ warnings.push('Added container object with innerBorder, outerBorder, gradient')
267
+ }
268
+
269
+ // Конвертируем borderRadius из строки в число если нужно
270
+ if (typeof config.settings.borderRadius === 'string') {
271
+ const borderRadiusMap: Record<string, number> = {
272
+ '0': 0,
273
+ 'sm': 4,
274
+ 'md': 8,
275
+ 'lg': 12,
276
+ }
277
+ config.settings.borderRadius = borderRadiusMap[config.settings.borderRadius] ?? 12
278
+ warnings.push(`Конвертирован borderRadius из строки в число: ${config.settings.borderRadius}`)
279
+ }
280
+
281
+ return this.createSuccessResult(config, warnings)
282
+ } catch (error) {
283
+ return this.createErrorResult([`Ошибка при добавлении theme и container: ${error}`])
284
+ }
285
+ }
286
+ }
287
+
288
+ /** Стратегия добавления border, sideMargin, borderRadius в top.params для V2->V3 */
289
+ export class AddTopParamsV2toV3Strategy extends BaseMigrationStrategy {
290
+ name = 'AddTopParamsV2toV3'
291
+ description = 'Добавляет border, sideMargin, borderRadius в sections.top.params'
292
+ appliesTo = { from: '2.0' as const, to: '3.0' as const }
293
+
294
+ apply(context: MigrationContext): MigrationStepResult {
295
+ try {
296
+ const config = { ...context.config }
297
+ const warnings: string[] = []
298
+
299
+ if (!config.sections?.top?.params) {
300
+ config.sections.top = config.sections.top || {}
301
+ config.sections.top.params = {}
302
+ }
303
+
304
+ // Добавляем border если его нет
305
+ if (!config.sections.top.params.border) {
306
+ config.sections.top.params.border = {
307
+ width: DEFAULT_CONFIG.sections.top.params.border?.width || 0,
308
+ color: DEFAULT_CONFIG.sections.top.params.border?.color || 'transparent',
309
+ }
310
+ warnings.push('Добавлено поле border в sections.top.params')
311
+ }
312
+
313
+ // Добавляем sideMargin если его нет
314
+ if (config.sections.top.params.sideMargin === undefined) {
315
+ config.sections.top.params.sideMargin = DEFAULT_CONFIG.sections.top.params.sideMargin || 0
316
+ warnings.push(`Добавлено поле sideMargin: ${config.sections.top.params.sideMargin}`)
317
+ }
318
+
319
+ // Добавляем borderRadius если его нет
320
+ if (config.sections.top.params.borderRadius === undefined) {
321
+ config.sections.top.params.borderRadius = DEFAULT_CONFIG.sections.top.params.borderRadius || 12
322
+ warnings.push(`Добавлено поле borderRadius: ${config.sections.top.params.borderRadius}`)
323
+ }
324
+
325
+ return this.createSuccessResult(config, warnings)
326
+ } catch (error) {
327
+ return this.createErrorResult([`Ошибка при добавлении полей top.params: ${error}`])
328
+ }
329
+ }
330
+ }
331
+
332
+ /** Стратегия добавления dataAction в inside для V2->V3 */
333
+ export class AddDataActionV2toV3Strategy extends BaseMigrationStrategy {
334
+ name = 'AddDataActionV2toV3'
335
+ description = 'Добавляет dataAction в sections.inside'
336
+ appliesTo = { from: '2.0' as const, to: '3.0' as const }
337
+
338
+ apply(context: MigrationContext): MigrationStepResult {
339
+ try {
340
+ const config = { ...context.config }
341
+ const warnings: string[] = []
342
+
343
+ if (!config.sections?.inside) {
344
+ config.sections.inside = {}
345
+ }
346
+
347
+ // Normalize dataAction to the V3 object shape (supports legacy string configs).
348
+ const defaultDataActionRaw = (DEFAULT_CONFIG as any)?.sections?.inside?.dataAction
349
+ const defaultDataAction =
350
+ defaultDataActionRaw && typeof defaultDataActionRaw === 'object'
351
+ ? defaultDataActionRaw
352
+ : {
353
+ type: 'steps',
354
+ headerFillColor: '#595959',
355
+ headerText: '#fff',
356
+ bodyFillColor: '#595959',
357
+ activeStepColor: '#fff',
358
+ pastStepColor: '#fff',
359
+ strokeColor: '#595959',
360
+ strokeWidth: 0,
361
+ }
362
+
363
+ const cloneDefault = () => JSON.parse(JSON.stringify(defaultDataAction))
364
+
365
+ const current = (config.sections.inside as any).dataAction
366
+ if (!current) {
367
+ ;(config.sections.inside as any).dataAction = cloneDefault()
368
+ warnings.push(`Added dataAction object (type: '${(config.sections.inside as any).dataAction.type}')`)
369
+ } else if (typeof current === 'string') {
370
+ ;(config.sections.inside as any).dataAction = {
371
+ ...cloneDefault(),
372
+ type: current,
373
+ }
374
+ warnings.push(`Upgraded dataAction from string to object (type: '${current}')`)
375
+ } else if (typeof current === 'object') {
376
+ // Fill missing fields from defaults, but keep user's existing values.
377
+ ;(config.sections.inside as any).dataAction = {
378
+ ...cloneDefault(),
379
+ ...current,
380
+ }
381
+ if (!(config.sections.inside as any).dataAction.type) {
382
+ ;(config.sections.inside as any).dataAction.type = cloneDefault().type
383
+ warnings.push(`Filled missing dataAction.type with default ('${(config.sections.inside as any).dataAction.type}')`)
384
+ }
385
+ }
386
+
387
+ return this.createSuccessResult(config, warnings)
388
+ } catch (error) {
389
+ return this.createErrorResult([`Ошибка при добавлении dataAction: ${error}`])
390
+ }
391
+ }
392
+ }
393
+
394
+ /** Стратегия расширения welcomeMessage для V2->V3 */
395
+ export class EnhanceWelcomeMessageV2toV3Strategy extends BaseMigrationStrategy {
396
+ name = 'EnhanceWelcomeMessageV2toV3'
397
+ description = 'Расширяет welcomeMessage с borderColor и другими полями'
398
+ appliesTo = { from: '2.0' as const, to: '3.0' as const }
399
+
400
+ apply(context: MigrationContext): MigrationStepResult {
401
+ try {
402
+ const config = { ...context.config }
403
+ const warnings: string[] = []
404
+
405
+ if (!config.sections?.inside?.welcomeMessage) {
406
+ config.sections.inside.welcomeMessage = {}
407
+ }
408
+
409
+ const welcomeMsg = config.sections.inside.welcomeMessage
410
+ const defaultWelcome = DEFAULT_CONFIG.sections.inside.welcomeMessage
411
+
412
+ // Добавляем недостающие поля
413
+ if (!welcomeMsg.borderColor && defaultWelcome.borderColor) {
414
+ welcomeMsg.borderColor = defaultWelcome.borderColor
415
+ warnings.push(`Добавлено поле borderColor для welcomeMessage`)
416
+ }
417
+
418
+ if (!welcomeMsg.bgType && defaultWelcome.bgType) {
419
+ welcomeMsg.bgType = defaultWelcome.bgType
420
+ warnings.push(`Добавлено поле bgType для welcomeMessage: '${welcomeMsg.bgType}'`)
421
+ }
422
+
423
+ if (!welcomeMsg.bgColor && defaultWelcome.bgColor) {
424
+ welcomeMsg.bgColor = defaultWelcome.bgColor
425
+ warnings.push(`Добавлено поле bgColor для welcomeMessage`)
426
+ }
427
+
428
+ if (welcomeMsg.borderWidth === undefined && defaultWelcome.borderWidth !== undefined) {
429
+ welcomeMsg.borderWidth = defaultWelcome.borderWidth
430
+ warnings.push(`Добавлено поле borderWidth для welcomeMessage`)
431
+ }
432
+
433
+ if (!welcomeMsg.fontSize && defaultWelcome.fontSize) {
434
+ welcomeMsg.fontSize = defaultWelcome.fontSize
435
+ warnings.push(`Добавлено поле fontSize для welcomeMessage`)
436
+ }
437
+
438
+ if (!welcomeMsg.size && defaultWelcome.size) {
439
+ welcomeMsg.size = defaultWelcome.size
440
+ warnings.push(`Добавлено поле size для welcomeMessage`)
441
+ }
442
+
443
+ if (!welcomeMsg.borderRadius && defaultWelcome.borderRadius) {
444
+ welcomeMsg.borderRadius = defaultWelcome.borderRadius
445
+ warnings.push(`Добавлено поле borderRadius для welcomeMessage`)
446
+ }
447
+
448
+ return this.createSuccessResult(config, warnings)
449
+ } catch (error) {
450
+ return this.createErrorResult([`Ошибка при расширении welcomeMessage: ${error}`])
451
+ }
452
+ }
453
+ }
454
+
455
+ /** Стратегия добавления btnVoice в bottom для V2->V3 */
456
+ export class AddVoiceButtonV2toV3Strategy extends BaseMigrationStrategy {
457
+ name = 'AddVoiceButtonV2toV3'
458
+ description = 'Добавляет btnVoice в sections.bottom'
459
+ appliesTo = { from: '2.0' as const, to: '3.0' as const }
460
+
461
+ apply(context: MigrationContext): MigrationStepResult {
462
+ try {
463
+ const config = { ...context.config }
464
+ const warnings: string[] = []
465
+
466
+ if (!config.sections?.bottom) {
467
+ config.sections.bottom = {}
468
+ }
469
+
470
+ // Добавляем btnVoice если его нет
471
+ if (!config.sections.bottom.btnVoice) {
472
+ config.sections.bottom.btnVoice = {
473
+ color: DEFAULT_CONFIG.sections.bottom.btnVoice?.color || '#fff',
474
+ bgColor: DEFAULT_CONFIG.sections.bottom.btnVoice?.bgColor || 'rgba(255, 255, 255, 0.10)',
475
+ showType: DEFAULT_CONFIG.sections.bottom.btnVoice?.showType || 'icon',
476
+ borderRadius: DEFAULT_CONFIG.sections.bottom.btnVoice?.borderRadius || 50,
477
+ borderColor: DEFAULT_CONFIG.sections.bottom.btnVoice?.borderColor || '#595959',
478
+ borderWidth: DEFAULT_CONFIG.sections.bottom.btnVoice?.borderWidth || 1,
479
+ size: DEFAULT_CONFIG.sections.bottom.btnVoice?.size || 'md',
480
+ fontSize: DEFAULT_CONFIG.sections.bottom.btnVoice?.fontSize || 12,
481
+ icon: DEFAULT_CONFIG.sections.bottom.btnVoice?.icon || {
482
+ showIcon: true,
483
+ src: '<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 1.5C8.20156 1.5 7.5 2.20156 7.5 3V9C7.5 9.79844 8.20156 10.5 9 10.5C9.79844 10.5 10.5 9.79844 10.5 9V3C10.5 2.20156 9.79844 1.5 9 1.5Z" fill="currentColor"/><path d="M13.5 7.5C13.0852 7.5 12.75 7.83516 12.75 8.25V9C12.75 10.2422 11.7422 11.25 10.5 11.25C9.25781 11.25 8.25 10.2422 8.25 9V8.25C8.25 7.83516 7.91484 7.5 7.5 7.5C7.08516 7.5 6.75 7.83516 6.75 8.25V9C6.75 10.8609 8.13906 12.375 9.9375 12.6562V14.25H7.5C7.08516 14.25 6.75 14.5852 6.75 15C6.75 15.4148 7.08516 15.75 7.5 15.75H10.5C10.9148 15.75 11.25 15.4148 11.25 15C11.25 14.5852 10.9148 14.25 10.5 14.25H10.3125V12.6562C12.1109 12.375 13.5 10.8609 13.5 9V8.25C13.5 7.83516 13.1648 7.5 12.75 7.5Z" fill="currentColor"/></svg>',
484
+ color: '#fff',
485
+ size: 18,
486
+ },
487
+ }
488
+ if(!config.sections.bottom.btnVoice.bgColor) {
489
+ config.sections.bottom.btnVoice.bgColor = DEFAULT_CONFIG.sections.bottom.btnVoice.bgColor
490
+ warnings.push(`Добавлено поле bgColor для btnVoice: '${config.sections.bottom.btnVoice.bgColor}'`)
491
+ }
492
+ warnings.push('Добавлен btnVoice в sections.bottom')
493
+ }
494
+
495
+ return this.createSuccessResult(config, warnings)
496
+ } catch (error) {
497
+ return this.createErrorResult([`Ошибка при добавлении btnVoice: ${error}`])
498
+ }
499
+ }
500
+ }
501
+
502
+ /** Реестр всех стратегий миграции V2->V3 */
503
+ export const V2_TO_V3_STRATEGIES: MigrationStrategy[] = [
504
+ new AddThemeAndContainerV2toV3Strategy(),
505
+ new AddTopParamsV2toV3Strategy(),
506
+ new AddDataActionV2toV3Strategy(),
507
+ new EnhanceWelcomeMessageV2toV3Strategy(),
508
+ new AddVoiceButtonV2toV3Strategy()
509
+ ]
510
+
234
511
  /** Получить все стратегии для конкретного перехода версий */
235
512
  export function getStrategiesForMigration(from: string, to: string): MigrationStrategy[] {
513
+ // Reuse V2->V3 strategies for any 3.0->3.1 hop to avoid empty step.
514
+ if (from === '3.0' && to === '3.1') {
515
+ return V2_TO_V3_STRATEGIES.map(strategy => {
516
+ // Clone strategy to avoid mutating original appliesTo; preserve methods.
517
+ const clone = Object.create(strategy) as MigrationStrategy
518
+ clone.appliesTo = { from: '3.0' as const, to: '3.1' as const }
519
+ return clone
520
+ })
521
+ }
522
+
236
523
  const allStrategies = [
237
- ...V1_TO_V2_STRATEGIES
238
- // Здесь можно добавить стратегии для других версий: V2_TO_V3_STRATEGIES и т.д.
524
+ ...V1_TO_V2_STRATEGIES,
525
+ ...V2_TO_V3_STRATEGIES
239
526
  ]
240
527
 
241
528
  return allStrategies.filter(strategy =>
@@ -246,7 +533,7 @@ export function getStrategiesForMigration(from: string, to: string): MigrationSt
246
533
  /** Получить все доступные стратегии */
247
534
  export function getAllStrategies(): MigrationStrategy[] {
248
535
  return [
249
- ...V1_TO_V2_STRATEGIES
250
- // Добавляйте сюда новые группы стратегий для других версий
536
+ ...V1_TO_V2_STRATEGIES,
537
+ ...V2_TO_V3_STRATEGIES
251
538
  ]
252
539
  }
@@ -5,7 +5,16 @@
5
5
  import { WidgetConfig } from '../config.types'
6
6
 
7
7
  /** Версии конфигурации */
8
- export type ConfigVersion = '1.0' | '2.0' | '3.0'
8
+ export type ConfigVersion = '1.0' | '2.0' | '3.0' | '3.1'
9
+
10
+ /**
11
+ * Ordered list of supported config versions.
12
+ * Keep this in sync with `ConfigVersion` union above.
13
+ */
14
+ export const CONFIG_VERSIONS = ['1.0', '2.0', '3.0', '3.1'] as const satisfies ReadonlyArray<ConfigVersion>
15
+
16
+ /** Latest supported config version. */
17
+ export const LATEST_CONFIG_VERSION: ConfigVersion = CONFIG_VERSIONS[CONFIG_VERSIONS.length - 1]
9
18
 
10
19
  /** Результат миграции */
11
20
  export interface MigrationResult<T = WidgetConfig> {
@@ -174,6 +183,7 @@ export type ConfigByVersion = {
174
183
  '1.0': ConfigV1
175
184
  '2.0': ConfigV2
176
185
  '3.0': WidgetConfig // Для будущих версий
186
+ '3.1': WidgetConfig
177
187
  }
178
188
 
179
189
  /** Фабрика для создания пустых конфигураций */