apptify 0.5.1 → 0.6.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 (67) hide show
  1. package/README.md +19 -66
  2. package/dist/apptify.css +1 -1
  3. package/dist/apptify.js +2298 -2140
  4. package/dist/components/AppleCard.vue.d.ts +76 -0
  5. package/dist/components/button.d.ts +3 -3
  6. package/dist/components/content.d.ts +0 -90
  7. package/dist/components/foundation.d.ts +201 -129
  8. package/dist/components/link.d.ts +31 -0
  9. package/dist/components/overlays.d.ts +8 -2
  10. package/dist/core/context.d.ts +11 -0
  11. package/dist/core/overlay-surface.d.ts +6 -0
  12. package/dist/core/popup-motion.d.ts +5 -5
  13. package/dist/core/popup-placement.d.ts +3 -2
  14. package/dist/index.d.ts +144 -79
  15. package/docs/COMPONENTS.md +23 -9
  16. package/docs/INPUT-WORKSHOP.md +59 -0
  17. package/docs/PLAYGROUND-TEMPLATE.md +9 -9
  18. package/package.json +5 -1
  19. package/templates/playground/README.md +4 -4
  20. package/templates/playground/index.html +1 -1
  21. package/templates/playground/package.json +6 -2
  22. package/templates/playground/source-snapshot.json +138 -53
  23. package/templates/playground/{playground → src}/App.vue +5 -4
  24. package/templates/playground/{playground → src}/ComponentDemo.vue +9 -10
  25. package/templates/playground/{playground → src}/catalog.ts +3 -4
  26. package/templates/playground/src/components/ComponentIndex.vue +43 -0
  27. package/templates/playground/src/components/DirectoryDialog.vue +20 -0
  28. package/templates/playground/src/components/PageFooter.vue +7 -0
  29. package/templates/playground/{playground → src}/components/UserMenu.vue +11 -11
  30. package/templates/playground/src/editor/AppleInputExample.vue +78 -0
  31. package/templates/playground/src/editor/AppleInputPreview.vue +82 -0
  32. package/templates/playground/src/editor/ComponentDocumentLink.vue +19 -0
  33. package/templates/playground/src/editor/ComponentWorkshop.vue +81 -0
  34. package/templates/playground/src/editor/ConfigurableEditor.vue +35 -0
  35. package/templates/playground/src/editor/LiveVueEditor.vue +133 -0
  36. package/templates/playground/src/editor/apple-input-source.ts +2 -0
  37. package/templates/playground/src/editor/apple-input.ts +48 -0
  38. package/templates/playground/src/editor/contract.ts +14 -0
  39. package/templates/playground/src/editor/documents.ts +20 -0
  40. package/templates/playground/src/editor/input-playground.ts +59 -0
  41. package/templates/playground/src/editor/runtime.ts +5 -0
  42. package/templates/playground/src/editor/sections.ts +10 -0
  43. package/templates/playground/{playground → src}/style.css +40 -39
  44. package/templates/playground/{playground → src}/views/[...all].vue +2 -2
  45. package/templates/playground/src/views/component-docs/[component].vue +162 -0
  46. package/templates/playground/src/views/components.vue +148 -0
  47. package/templates/playground/src/views/index.vue +73 -0
  48. package/templates/playground/src/views/settings.vue +224 -0
  49. package/templates/playground/tooling/playground-editor.mjs +114 -0
  50. package/templates/playground/tooling/prepare-input-source.mjs +38 -0
  51. package/templates/playground/tsconfig.json +2 -2
  52. package/templates/playground/vite.config.ts +3 -1
  53. package/tooling/playground-editor.mjs +114 -0
  54. package/tooling/prepare-input-source.mjs +38 -0
  55. package/tooling/prepare-playground.mjs +27 -14
  56. package/tooling/test-create-apptify.mjs +15 -5
  57. package/tooling/test-playground-package.mjs +25 -11
  58. package/templates/playground/playground/components/ComponentIndex.vue +0 -62
  59. package/templates/playground/playground/components/PageFooter.vue +0 -3
  60. package/templates/playground/playground/views/components.vue +0 -126
  61. package/templates/playground/playground/views/index.vue +0 -75
  62. package/templates/playground/playground/views/settings.vue +0 -98
  63. /package/templates/playground/{playground → src}/components/not-found-paper-scene.vue +0 -0
  64. /package/templates/playground/{playground → src}/components/not-found-paper-story.ts +0 -0
  65. /package/templates/playground/{playground → src}/env.d.ts +0 -0
  66. /package/templates/playground/{playground → src}/main.ts +0 -0
  67. /package/templates/playground/{playground → src}/router/index.ts +0 -0
@@ -71,6 +71,7 @@ export declare const AppleDialog: import("vue").DefineComponent<import("vue").Ex
71
71
  disposeLayer: (() => void) | null;
72
72
  isTop: boolean;
73
73
  depth: number;
74
+ present: boolean;
74
75
  }, {
75
76
  resolvedMotion(): string;
76
77
  }, {
@@ -217,6 +218,7 @@ export declare const AppleDrawer: import("vue").DefineComponent<import("vue").Ex
217
218
  disposeLayer: (() => void) | null;
218
219
  isTop: boolean;
219
220
  depth: number;
221
+ present: boolean;
220
222
  }, {
221
223
  resolvedMotion(): string;
222
224
  }, {
@@ -363,6 +365,7 @@ export declare const AppleSheet: import("vue").DefineComponent<import("vue").Ext
363
365
  disposeLayer: (() => void) | null;
364
366
  isTop: boolean;
365
367
  depth: number;
368
+ present: boolean;
366
369
  }, {
367
370
  resolvedMotion(): string;
368
371
  }, {
@@ -598,13 +601,13 @@ export declare const ApplePopover: import("vue").DefineComponent<import("vue").E
598
601
  internalOpen: boolean;
599
602
  depth: number;
600
603
  isTop: boolean;
604
+ present: boolean;
601
605
  disposeLayer: (() => void) | null;
602
606
  disposePosition: (() => void) | null;
603
607
  hoverTimer: ReturnType<typeof setTimeout> | null;
604
608
  positioned: boolean;
605
609
  positioner: PopupPositioner | null;
606
610
  positionPanel: HTMLElement | null;
607
- interruptedPopup: number | undefined;
608
611
  }, {
609
612
  opened(): boolean;
610
613
  }, {
@@ -983,6 +986,7 @@ export declare const overlayComponents: {
983
986
  disposeLayer: (() => void) | null;
984
987
  isTop: boolean;
985
988
  depth: number;
989
+ present: boolean;
986
990
  }, {
987
991
  resolvedMotion(): string;
988
992
  }, {
@@ -1129,6 +1133,7 @@ export declare const overlayComponents: {
1129
1133
  disposeLayer: (() => void) | null;
1130
1134
  isTop: boolean;
1131
1135
  depth: number;
1136
+ present: boolean;
1132
1137
  }, {
1133
1138
  resolvedMotion(): string;
1134
1139
  }, {
@@ -1275,6 +1280,7 @@ export declare const overlayComponents: {
1275
1280
  disposeLayer: (() => void) | null;
1276
1281
  isTop: boolean;
1277
1282
  depth: number;
1283
+ present: boolean;
1278
1284
  }, {
1279
1285
  resolvedMotion(): string;
1280
1286
  }, {
@@ -1510,13 +1516,13 @@ export declare const overlayComponents: {
1510
1516
  internalOpen: boolean;
1511
1517
  depth: number;
1512
1518
  isTop: boolean;
1519
+ present: boolean;
1513
1520
  disposeLayer: (() => void) | null;
1514
1521
  disposePosition: (() => void) | null;
1515
1522
  hoverTimer: ReturnType<typeof setTimeout> | null;
1516
1523
  positioned: boolean;
1517
1524
  positioner: PopupPositioner | null;
1518
1525
  positionPanel: HTMLElement | null;
1519
- interruptedPopup: number | undefined;
1520
1526
  }, {
1521
1527
  opened(): boolean;
1522
1528
  }, {
@@ -316,6 +316,7 @@ export interface AppleOptions {
316
316
  theme?: string;
317
317
  themes?: Record<string, AppleTheme>;
318
318
  motion?: Motion;
319
+ ripple?: boolean;
319
320
  glass?: Partial<AppleGlassSettings>;
320
321
  persist?: boolean;
321
322
  storageKey?: string;
@@ -362,6 +363,16 @@ export declare function createApple(options?: AppleOptions): import("vue").Raw<{
362
363
  reduced: boolean;
363
364
  set: (mode: Motion) => void;
364
365
  }>;
366
+ ripple: Ref<{
367
+ enabled: boolean;
368
+ set: (enabled: boolean) => void;
369
+ }, {
370
+ enabled: boolean;
371
+ set(enabled: boolean): void;
372
+ } | {
373
+ enabled: boolean;
374
+ set: (enabled: boolean) => void;
375
+ }>;
365
376
  glass: Ref<{
366
377
  set: (value: Partial<AppleGlassSettings>) => void;
367
378
  reset: () => void;
@@ -0,0 +1,6 @@
1
+ import type { ObjectDirective } from 'vue';
2
+ /** The browser's top layer escapes clipping and transformed containing blocks
3
+ * without moving Vue's DOM, focus scope, or inherited theme out of its owner. */
4
+ export declare function showOverlaySurface(element: HTMLElement): void;
5
+ export declare function hideOverlaySurface(element: HTMLElement): void;
6
+ export declare const OverlaySurface: ObjectDirective<HTMLElement>;
@@ -2,11 +2,11 @@ import { type VNode, type VNodeChild } from 'vue';
2
2
  export declare function freezePopup(element: Element): number | undefined;
3
3
  export declare function finishPopup(element: HTMLElement): void;
4
4
  export declare function resetPopup(element: Element): void;
5
- export declare function preparePopup(element: Element, reveal: boolean, interrupted?: number): void;
6
- /** One scalar controls visibility. Reproject it when placement changes so an
7
- * in-flight reveal/reversal never keeps the opening side's clip or translation. */
8
- export declare function animatePopup(element: Element, opened: boolean, done: () => void, reveal?: boolean): void;
9
- /** Shared field transition keeps the full panel layout stable during clipping. */
5
+ export declare function preparePopup(element: Element, interrupted?: number): void;
6
+ /** Animate the complete surface, including its shadow. Keep the current frame
7
+ * until its replacement is ready, including on reversal and placement changes. */
8
+ export declare function animatePopup(element: Element, opened: boolean, done: () => void): void;
9
+ /** Shared field transition keeps the full panel layout stable during motion. */
10
10
  export declare function popupTransition(content: VNodeChild, name?: string, persisted?: boolean, gap?: number): VNode<import("vue").RendererNode, import("vue").RendererElement, {
11
11
  [key: string]: any;
12
12
  }>;
@@ -19,9 +19,10 @@ interface PopupPositionOptions {
19
19
  fixed?: boolean;
20
20
  gap?: number;
21
21
  }
22
- /** Keep the DOM node, not a component ref: Vue clears refs before leave finishes. */
22
+ /** Keep measurements in viewport coordinates and never uncap a live scrollport
23
+ * to measure it: doing so clamps scrollTop to zero before constraints return. */
23
24
  export declare function createPopupPositioner(panel: HTMLElement, options: PopupPositionOptions): PopupPositioner;
24
- /** Inline field popups stay attached to their anchor; placement is live through leave. */
25
+ /** Field popups retain their DOM/focus owner while rendering in the top layer. */
25
26
  export declare function updateFieldPopup(element: HTMLElement): void;
26
27
  export declare function unmountFieldPopup(element: HTMLElement): void;
27
28
  export declare function mountFieldPopup(element: HTMLElement, gap?: number): void;
package/dist/index.d.ts CHANGED
@@ -272,6 +272,7 @@ export declare const components: {
272
272
  disposeLayer: (() => void) | null;
273
273
  isTop: boolean;
274
274
  depth: number;
275
+ present: boolean;
275
276
  }, {
276
277
  resolvedMotion(): string;
277
278
  }, {
@@ -418,6 +419,7 @@ export declare const components: {
418
419
  disposeLayer: (() => void) | null;
419
420
  isTop: boolean;
420
421
  depth: number;
422
+ present: boolean;
421
423
  }, {
422
424
  resolvedMotion(): string;
423
425
  }, {
@@ -564,6 +566,7 @@ export declare const components: {
564
566
  disposeLayer: (() => void) | null;
565
567
  isTop: boolean;
566
568
  depth: number;
569
+ present: boolean;
567
570
  }, {
568
571
  resolvedMotion(): string;
569
572
  }, {
@@ -799,13 +802,13 @@ export declare const components: {
799
802
  internalOpen: boolean;
800
803
  depth: number;
801
804
  isTop: boolean;
805
+ present: boolean;
802
806
  disposeLayer: (() => void) | null;
803
807
  disposePosition: (() => void) | null;
804
808
  hoverTimer: ReturnType<typeof setTimeout> | null;
805
809
  positioned: boolean;
806
810
  positioner: import("./core/popup-placement").PopupPositioner | null;
807
811
  positionPanel: HTMLElement | null;
808
- interruptedPopup: number | undefined;
809
812
  }, {
810
813
  opened(): boolean;
811
814
  }, {
@@ -2352,51 +2355,6 @@ export declare const components: {
2352
2355
  threshold: number;
2353
2356
  backTop: boolean;
2354
2357
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2355
- AppleMarquee: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2356
- text: {
2357
- type: StringConstructor;
2358
- default: string;
2359
- };
2360
- duration: {
2361
- type: NumberConstructor;
2362
- default: number;
2363
- };
2364
- paused: BooleanConstructor;
2365
- label: {
2366
- type: StringConstructor;
2367
- default: string;
2368
- };
2369
- motion: {
2370
- type: import("vue").PropType<"auto" | "full" | "reduced" | "none" | "inherit">;
2371
- default: string;
2372
- };
2373
- }>, {}, {
2374
- userPaused: boolean;
2375
- }, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
2376
- text: {
2377
- type: StringConstructor;
2378
- default: string;
2379
- };
2380
- duration: {
2381
- type: NumberConstructor;
2382
- default: number;
2383
- };
2384
- paused: BooleanConstructor;
2385
- label: {
2386
- type: StringConstructor;
2387
- default: string;
2388
- };
2389
- motion: {
2390
- type: import("vue").PropType<"auto" | "full" | "reduced" | "none" | "inherit">;
2391
- default: string;
2392
- };
2393
- }>> & Readonly<{}>, {
2394
- text: string;
2395
- duration: number;
2396
- label: string;
2397
- motion: "auto" | "full" | "reduced" | "none" | "inherit";
2398
- paused: boolean;
2399
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2400
2358
  AppleStatistic: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2401
2359
  value: {
2402
2360
  type: (NumberConstructor | StringConstructor)[];
@@ -4105,6 +4063,16 @@ export declare const components: {
4105
4063
  reduced: boolean;
4106
4064
  set: (mode: import(".").Motion) => void;
4107
4065
  }>;
4066
+ ripple: import("vue").Ref<{
4067
+ enabled: boolean;
4068
+ set: (enabled: boolean) => void;
4069
+ }, {
4070
+ enabled: boolean;
4071
+ set(enabled: boolean): void;
4072
+ } | {
4073
+ enabled: boolean;
4074
+ set: (enabled: boolean) => void;
4075
+ }>;
4108
4076
  glass: import("vue").Ref<{
4109
4077
  set: (value: Partial<import(".").AppleGlassSettings>) => void;
4110
4078
  reset: () => void;
@@ -4442,6 +4410,16 @@ export declare const components: {
4442
4410
  reduced: boolean;
4443
4411
  set: (mode: import(".").Motion) => void;
4444
4412
  }>;
4413
+ ripple: import("vue").Ref<{
4414
+ enabled: boolean;
4415
+ set: (enabled: boolean) => void;
4416
+ }, {
4417
+ enabled: boolean;
4418
+ set(enabled: boolean): void;
4419
+ } | {
4420
+ enabled: boolean;
4421
+ set: (enabled: boolean) => void;
4422
+ }>;
4445
4423
  glass: import("vue").Ref<{
4446
4424
  set: (value: Partial<import(".").AppleGlassSettings>) => void;
4447
4425
  reset: () => void;
@@ -4787,6 +4765,16 @@ export declare const components: {
4787
4765
  reduced: boolean;
4788
4766
  set: (mode: import(".").Motion) => void;
4789
4767
  }>;
4768
+ ripple: import("vue").Ref<{
4769
+ enabled: boolean;
4770
+ set: (enabled: boolean) => void;
4771
+ }, {
4772
+ enabled: boolean;
4773
+ set(enabled: boolean): void;
4774
+ } | {
4775
+ enabled: boolean;
4776
+ set: (enabled: boolean) => void;
4777
+ }>;
4790
4778
  glass: import("vue").Ref<{
4791
4779
  set: (value: Partial<import(".").AppleGlassSettings>) => void;
4792
4780
  reset: () => void;
@@ -5086,7 +5074,7 @@ export declare const components: {
5086
5074
  }, true, {}, any>;
5087
5075
  AppleButton: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
5088
5076
  variant: {
5089
- type: import("vue").PropType<"primary" | "secondary" | "outline" | "ghost" | "danger">;
5077
+ type: import("vue").PropType<"primary" | "secondary" | "outline" | "danger">;
5090
5078
  default: string;
5091
5079
  };
5092
5080
  size: {
@@ -5113,7 +5101,7 @@ export declare const components: {
5113
5101
  };
5114
5102
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "click"[], "click", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
5115
5103
  variant: {
5116
- type: import("vue").PropType<"primary" | "secondary" | "outline" | "ghost" | "danger">;
5104
+ type: import("vue").PropType<"primary" | "secondary" | "outline" | "danger">;
5117
5105
  default: string;
5118
5106
  };
5119
5107
  size: {
@@ -5145,55 +5133,120 @@ export declare const components: {
5145
5133
  disabled: boolean;
5146
5134
  iconOnly: boolean;
5147
5135
  loading: boolean;
5148
- variant: "secondary" | "danger" | "primary" | "outline" | "ghost";
5136
+ variant: "secondary" | "danger" | "primary" | "outline";
5149
5137
  ripple: boolean;
5150
5138
  type: "reset" | "submit" | "button";
5151
5139
  motion: import(".").ComponentMotion;
5152
5140
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
5153
5141
  AppleLink: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
5142
+ as: {
5143
+ type: import("vue").PropType<"a" | "button">;
5144
+ default: string;
5145
+ };
5154
5146
  href: StringConstructor;
5155
5147
  external: BooleanConstructor;
5156
5148
  disabled: BooleanConstructor;
5157
- }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
5149
+ icon: import("vue").PropType<import("vue").Component>;
5150
+ iconOnly: BooleanConstructor;
5151
+ label: StringConstructor;
5152
+ }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "click"[], "click", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
5153
+ as: {
5154
+ type: import("vue").PropType<"a" | "button">;
5155
+ default: string;
5156
+ };
5158
5157
  href: StringConstructor;
5159
5158
  external: BooleanConstructor;
5160
5159
  disabled: BooleanConstructor;
5161
- }>> & Readonly<{}>, {
5160
+ icon: import("vue").PropType<import("vue").Component>;
5161
+ iconOnly: BooleanConstructor;
5162
+ label: StringConstructor;
5163
+ }>> & Readonly<{
5164
+ onClick?: ((...args: any[]) => any) | undefined;
5165
+ }>, {
5162
5166
  disabled: boolean;
5167
+ iconOnly: boolean;
5163
5168
  external: boolean;
5169
+ as: "a" | "button";
5164
5170
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
5165
- AppleCard: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
5166
- title: StringConstructor;
5167
- subtitle: StringConstructor;
5168
- text: StringConstructor;
5169
- eyebrow: StringConstructor;
5171
+ AppleCard: {
5172
+ new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
5173
+ icon: import("vue").PropType<import("vue").Component | string>;
5174
+ iconColor: StringConstructor;
5175
+ title: StringConstructor;
5176
+ subtitle: StringConstructor;
5177
+ text: StringConstructor;
5178
+ eyebrow: StringConstructor;
5179
+ image: StringConstructor;
5180
+ imageAlt: {
5181
+ type: StringConstructor;
5182
+ default: string;
5183
+ };
5184
+ href: StringConstructor;
5185
+ zoom: {
5186
+ type: import("vue").PropType<"big" | "small" | "none">;
5187
+ default: string;
5188
+ };
5189
+ shadow: {
5190
+ type: import("vue").PropType<"normal" | "static" | "focused" | "none">;
5191
+ default: string;
5192
+ };
5193
+ motion: {
5194
+ type: import("vue").PropType<import(".").ComponentMotion>;
5195
+ default: string;
5196
+ };
5197
+ }>> & Readonly<{}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, import("vue").PublicProps, {
5198
+ shadow: "none" | "static" | "normal" | "focused";
5199
+ motion: import(".").ComponentMotion;
5200
+ zoom: "none" | "big" | "small";
5201
+ imageAlt: string;
5202
+ }, true, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
5203
+ P: {};
5204
+ B: {};
5205
+ D: {};
5206
+ C: {};
5207
+ M: {};
5208
+ Defaults: {};
5209
+ }, Readonly<import("vue").ExtractPropTypes<{
5210
+ icon: import("vue").PropType<import("vue").Component | string>;
5211
+ iconColor: StringConstructor;
5212
+ title: StringConstructor;
5213
+ subtitle: StringConstructor;
5214
+ text: StringConstructor;
5215
+ eyebrow: StringConstructor;
5216
+ image: StringConstructor;
5217
+ imageAlt: {
5218
+ type: StringConstructor;
5219
+ default: string;
5220
+ };
5221
+ href: StringConstructor;
5222
+ zoom: {
5223
+ type: import("vue").PropType<"big" | "small" | "none">;
5224
+ default: string;
5225
+ };
5226
+ shadow: {
5227
+ type: import("vue").PropType<"normal" | "static" | "focused" | "none">;
5228
+ default: string;
5229
+ };
5230
+ motion: {
5231
+ type: import("vue").PropType<import(".").ComponentMotion>;
5232
+ default: string;
5233
+ };
5234
+ }>> & Readonly<{}>, {}, {}, {}, {}, {
5235
+ shadow: "none" | "static" | "normal" | "focused";
5236
+ motion: import(".").ComponentMotion;
5237
+ zoom: "none" | "big" | "small";
5238
+ imageAlt: string;
5239
+ }>;
5240
+ __isFragment?: never;
5241
+ __isTeleport?: never;
5242
+ __isSuspense?: never;
5243
+ } & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
5170
5244
  icon: import("vue").PropType<import("vue").Component | string>;
5171
5245
  iconColor: StringConstructor;
5172
- image: StringConstructor;
5173
- imageAlt: {
5174
- type: StringConstructor;
5175
- default: string;
5176
- };
5177
- href: StringConstructor;
5178
- zoom: {
5179
- type: import("vue").PropType<"big" | "small" | "none">;
5180
- default: string;
5181
- };
5182
- shadow: {
5183
- type: import("vue").PropType<"normal" | "static" | "focused" | "none">;
5184
- default: string;
5185
- };
5186
- motion: {
5187
- type: import("vue").PropType<import(".").ComponentMotion>;
5188
- default: string;
5189
- };
5190
- }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
5191
5246
  title: StringConstructor;
5192
5247
  subtitle: StringConstructor;
5193
5248
  text: StringConstructor;
5194
5249
  eyebrow: StringConstructor;
5195
- icon: import("vue").PropType<import("vue").Component | string>;
5196
- iconColor: StringConstructor;
5197
5250
  image: StringConstructor;
5198
5251
  imageAlt: {
5199
5252
  type: StringConstructor;
@@ -5212,12 +5265,24 @@ export declare const components: {
5212
5265
  type: import("vue").PropType<import(".").ComponentMotion>;
5213
5266
  default: string;
5214
5267
  };
5215
- }>> & Readonly<{}>, {
5268
+ }>> & Readonly<{}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
5216
5269
  shadow: "none" | "static" | "normal" | "focused";
5217
5270
  motion: import(".").ComponentMotion;
5218
5271
  zoom: "none" | "big" | "small";
5219
5272
  imageAlt: string;
5220
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
5273
+ }, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
5274
+ $slots: {
5275
+ media?: (props: {}) => any;
5276
+ } & {
5277
+ icon?: (props: {}) => any;
5278
+ } & {
5279
+ title?: (props: {}) => any;
5280
+ } & {
5281
+ default?: (props: {}) => any;
5282
+ } & {
5283
+ actions?: (props: {}) => any;
5284
+ };
5285
+ });
5221
5286
  AppleImage: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
5222
5287
  preview: {
5223
5288
  type: BooleanConstructor;
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 公共约定
6
6
 
7
- `secondary` 与 `outline` 都是描边按钮,`ghost` 是纯文字按钮且始终不启用 Ripple。所有 API 可直接从 JavaScript 和普通 Vue `<script>` 使用,TypeScript 不是消费前提。
7
+ `secondary` 与 `outline` 都是描边按钮,纯文字操作使用 `AppleLink`,始终不启用 Ripple。所有 API 可直接从 JavaScript 和普通 Vue `<script>` 使用,TypeScript 不是消费前提。
8
8
 
9
9
  Tabs、TabBar、SegmentedControl、DatePicker 日期/时间页签均不使用 Ripple;保留选中指示器位移与内容切换动画。
10
10
 
@@ -15,6 +15,18 @@ Tabs、TabBar、SegmentedControl、DatePicker 日期/时间页签均不使用 Ri
15
15
  - 内容选项类型为 `AppleItem = { label; value; disabled?; description?; href?; content? }`;`value` 为唯一的 `string | number`。
16
16
  - 组件并非 Vuetify 同名组件的透传包装。只依赖这里声明的接口,不假设任意 `v-*` prop、slot 或事件都可直接使用。
17
17
 
18
+ ## Glass 通用样式
19
+
20
+ 导入 `apptify/style.css` 后,在 `<apple-provider>` 内给自定义元素添加 `.apple-glass`,即可应用跟随主题和全局 glass 设置的背景、文字颜色与背景模糊:
21
+
22
+ ```vue
23
+ <apple-provider>
24
+ <div class="apple-glass">自定义玻璃面板</div>
25
+ </apple-provider>
26
+ ```
27
+
28
+ 该类只提供材质与文字颜色,间距、圆角、边框和阴影由使用方设置。Provider 外使用默认浅色材质;Provider 内跟随 `glass.opacity` 与 `glass.blur` 配置。
29
+
18
30
  ## 动效组件 · 2
19
31
 
20
32
  | 组件 | Props | 说明 |
@@ -24,16 +36,16 @@ Tabs、TabBar、SegmentedControl、DatePicker 日期/时间页签均不使用 Ri
24
36
 
25
37
  全局入场使用 `v-apple-entrance="pageKey"` 放在一个页面容器上:首次挂载及 key 改变时整体由下向上 14px,不复制旧页、不执行离场、不改变透明度。不应嵌套应用到同一页面的多层内容。
26
38
 
27
- 另提供 `v-apple-ripple` 和 `v-apple-selection`;后者移动到后代 `[data-apple-selected="true"]`,也可传 `{selector}`。全局 none/reduced 与系统减少动态效果限制同样生效。
39
+ 另提供 `v-apple-ripple` 和 `v-apple-selection`;后者移动到后代 `[data-apple-selected="true"]`,也可传 `{selector}`。selection 遵循全局 none/reduced 与系统减少动态效果限制;ripple 在减弱动效下可手动开启,none 下始终禁用。
28
40
 
29
41
  ## 基础组件 · 9
30
42
 
31
43
  | 组件 | 主要 Props | Events / Slots / 说明 |
32
44
  | --- | --- | --- |
33
45
  | `AppleProvider` | `theme?: string`、`motion?: auto/full/reduced/none` | default slot;应用主题并自动挂载弹层宿主。无显式属性时复用插件上下文。 |
34
- | `AppleButton` | M;`variant=primary`(primary/secondary/outline/ghost/danger)、`size=medium`(small/medium/large)、`icon: Component`、`iconOnly`、`label`、`disabled`、`loading`、`ripple=true`、`href`、`type=button` | `click(event)`;default slot。纯图标按钮须提供 label。只有允许完整动效时启用 Ripple。 |
35
- | `AppleLink` | `href`、`external`、`disabled` | default slot;external 使用新窗口并设置 `noopener noreferrer`。 |
36
- | `AppleCard` | M;`title`、`subtitle`、`text`、`eyebrow`、`icon: Component 或图片 URL`、`iconColor`、`image`、`imageAlt`、`href`、`zoom=small`(big/small/none)、`shadow=normal`(normal/static/focused/none) | default、media、icon、title、actions slots;href 为标题链接,不会把所有嵌套控件变成一个大按钮。 |
46
+ | `AppleButton` | M;`variant=primary`(primary/secondary/outline/danger)、`size=medium`(small/medium/large)、`icon: Component`、`iconOnly`、`label`、`disabled`、`loading`、`ripple=true`、`href`、`type=button` | `click(event)`;default slot;图标位于文字右侧。纯图标按钮须提供 label。关闭动效时禁用 Ripple,其余模式遵循全局波纹开关。 |
47
+ | `AppleLink` | `as=a`(a/button)、`href`、`external`、`disabled`、`icon`、`iconOnly`、`label` | default slot;文字操作使用 as=button;external 使用新窗口并设置 `noopener noreferrer`。 |
48
+ | `AppleCard` | M;`title`、`subtitle`、`text`、`eyebrow`、`icon: Component 或图片 URL`、`iconColor`、`image`、`imageAlt`、`href`、`zoom=none`(big/small/none)、`shadow=normal`(normal/static/focused/none) | default、media、icon、title、actions slots;href 为标题链接,不会把所有嵌套控件变成一个大按钮。 |
37
49
  | `AppleImage` | M;`gallery: AppleImageItem | (string/AppleImageItem)[]`(唯一来源,默认空数组,单图可传对象);`preview=true`、`carousel=false`、`disabled=false`、`label`、`galleryLayout=compact`(compact/tiled/tiled-wrap,所有设备)、`galleryShape=natural`(natural/square)、`index=0`、`squared`、`aspectRatio='4/3'`、`fit=cover`(cover/contain) | caption 与 item({item,index,active}) slots;carousel 强制 compact、常显控件且保留自由滚动;默认点击预览;统一入口,按触屏能力选择预览交互;完整渲染图片组,compact 在固定框内横滑,桌面触控板支持自由连续横滑、一次手势可跨越多张,快速点击翻页延续当前位置和速度;hover 不缩放,多图显示左右翻页按钮(单图小窗与全屏均无翻页箭头),跨多张点击小点时直接衔接当前画面与目标图并支持连续改选,tiled 等高横向平铺,溢出时底部常显自定义滚动条,支持拖动、点击轨道与键盘,滑块比例随内容和容器尺寸同步,tiled-wrap 等宽保留图片比例,按列从上往下紧密堆叠,避免按行对齐产生空白;平铺 hover 只缩放当前图片;galleryShape=square 强制 1:1 并居中裁剪(覆盖 fit),squared 同样作用于图片组;`update:index`、`change(index)`;图片错误状态;squared 覆盖 aspectRatio。 |
38
50
  | `AppleSearch` | `v-model: string`、`placeholder='搜索'`、`label='搜索'`、`disabled` | `search(value)` 在 Enter 时发出;清空更新 model。 |
39
51
  | `AppleContainer` | `width=1200`(number/string) | default slot;数字宽度按 px,宽度不会超过可用空间。 |
@@ -42,15 +54,17 @@ Tabs、TabBar、SegmentedControl、DatePicker 日期/时间页签均不使用 Ri
42
54
 
43
55
  ## 表单组件 · 18
44
56
 
57
+ 字段名称、hint、错误提示和行内空白只用于展示,点击不会聚焦、展开或切换控件;直接操作输入框、选择器或开关本身。字段名称通过 ARIA 保留可访问性关联。
58
+
45
59
  | 组件 | 主要 Props | Events / Slots / 方法 |
46
60
  | --- | --- | --- |
47
61
  | `AppleInput` | F;`v-model: string/number`、`type=text`、`placeholder`、`clearable` | `change(value)`、`clear()`;prefix/suffix slots;`focus()`;输入事件实际返回字符串。password 类型带显隐按钮。 |
48
62
  | `AppleTextarea` | F;`v-model: string`、`placeholder`、`rows=4`、`maxlength`、`counter`、`resize=true` | `change(value)`;`focus()`;resize=true 允许纵向缩放。 |
49
63
  | `AppleSelect` | F;`v-model: string/number/null`、`items: AppleOption[]`、`placeholder='请选择'` | `change(value)`;自绘半透明模糊下拉,支持键盘导航和 required 校验。 |
50
64
  | `AppleAutocomplete` | F;`v-model: string/number/null`、`items`、`placeholder`、`emptyText`、`clearable=true`、`filter(query,item)` | `change(value)`、`search(query)`;`focus()`;方向键/Enter/Escape;是单选过滤,不是多选标签输入。 |
51
- | `AppleCheckbox` | F;`v-model: boolean`、`indeterminate` | `change(checked)`;default slot 替代 label 文本。 |
65
+ | `AppleCheckbox` | F;`v-model: boolean`、`indeterminate` | `change(checked)`;default slot 替代 label 文本,默认文字在左、开关在右;hint 在下方。 |
52
66
  | `AppleRadioGroup` | F;`v-model: string/number/null`、`items`、`inline`、`name` | `change(value)`;原生 radio group。 |
53
- | `AppleSwitch` | F;`v-model: boolean` | `change(checked)`;default slot 替代 label 文本。 |
67
+ | `AppleSwitch` | F;`v-model: boolean` | `change(checked)`;default slot 替代 label 文本。默认 width: 100%,label 和 hint 在左侧同一列,开关在右侧。 |
54
68
  | `AppleSlider` | F;`v-model: number`、`min=0`、`max=100`、`step=1`、`showValue=true`、`formatValue(value)` | `change(value)`;单值原生 range,不是双滑块范围选择。 |
55
69
  | `AppleStepper` | F;`v-model: number`、`min=-Infinity`、`max=Infinity`、`step=1` | `change(value)`;减/加按钮及可编辑数值输入;提交时约束范围。 |
56
70
  | `AppleSegmentedControl` | F;`v-model: string/number/null`、`items`、`name` | `change(value)`;基于 radio 的单选分段控件,不是 tabs 内容容器。 |
@@ -58,7 +72,7 @@ Tabs、TabBar、SegmentedControl、DatePicker 日期/时间页签均不使用 Ri
58
72
  | `AppleColorPicker` | F;`v-model: string='#0071e3'`、`showValue=true` | `change(value)`;自绘色板和 HEX 输入,不打开原生颜色弹窗。 |
59
73
  | `AppleUpload` | F;`v-model: File[]`、`accept`、`multiple`、`maxSize=Infinity`、`maxFiles=Infinity`、`capture=user/environment`、`buttonText` | `change(files)`、`reject({file,reason}[])`、`remove(file)`;default slot;maxSize 单位为字节;不发送网络请求。 |
60
74
  | `AppleForm` | M;`disabled`、`loading`、`validator(FormData): boolean/string/Promise` | `submit(FormData)`、`invalid({type,message?})`、`reset()`;default slot `{loading}`;实例方法 `validate(): Promise<boolean>`、`submit()`、`reset()`。 |
61
- | `AppleFormField` | F;`for` | default slot `{id,disabled,required,'aria-invalid','aria-describedby'}`;用于关联自定义输入及提示。 |
75
+ | `AppleFormField` | F;`for` | default slot `{id,disabled,required,'aria-label','aria-labelledby','aria-invalid','aria-describedby'}`;将 slot 属性绑定到自定义输入,以关联字段名称及提示。 |
62
76
  | `AppleOtpInput` | F;`label='验证码'`、`v-model: string`、`length=6`(1–12)、`numeric=true`、`name`、`mask` | `change(value)`、`complete(value)`;`focus(index=0)`;支持粘贴、退格、方向键与验证码自动填充提示。 |
63
77
  | `AppleCascader` | F;`v-model: (string/number)[]`、`items: AppleCascaderOption[]`、`placeholder`、`levelLabels: string[]`、`name` | `change(path)`、`complete(path)`;选项递归增加 `children`;不内置行政区划数据。 |
64
78
  | `AppleRate` | F;`label='评分'`、`v-model: number`、`max=5`(渲染 1–10)、`readonly`、`allowClear=true`、`name` | `change(value)`;整数星级;allowClear 时再次选择当前值返回 0;不支持半星。 |
@@ -111,7 +125,6 @@ validator 返回 `true` 才通过;字符串作为错误信息,`false` 显示
111
125
  | `AppleInfiniteScroll` | `loading`、`error: boolean/string`、`finished`、`disabled`、`distance=120`、`finishedText` | `load(done)`、`retry(done)`;default slot;IntersectionObserver 及手动加载按钮;完成后调用 done,或令 loading 从 true 回到 false。 |
112
126
  | `AppleBackTop` | `target: CSS selector=''`、`threshold=300`、`label`、`disabled` | `click(event)`;default slot;空 target 使用 window,达到滚动阈值才显示。 |
113
127
  | `AppleFloatingGroup` | `backTop=true`、`threshold=300`、`target`、`label` | default slot 放附加操作,回顶按钮始终排最下;默认固定右下并考虑安全区。 |
114
- | `AppleMarquee` | `text`、`duration=24`、`paused`、`label` | default slot;duration 单位为秒;带暂停按钮;减少动态效果时停止连续滚动。 |
115
128
  | `AppleStatistic` | 必填 `label`;`value: string/number`、`prefix`、`suffix`、`precision=0`、`locale=zh-CN`、`description` | default slot;数值本地化格式,不会自动请求统计数据。 |
116
129
 
117
130
  `AppleColumn = { key: string; label: string; sortable?: boolean; align?: 'left'|'center'|'right'; width?: number|string; minWidth?: number; maxWidth?: number; resizable?: boolean }`。表格 rows 应提供稳定唯一的 `rowKey`。
@@ -190,6 +203,7 @@ Modal slots:`title`、default `{close}`、footer `{close,confirm,cancel}`。
190
203
  | `overlays.entries.value` | 当前弹层列表,`Ref<OverlayEntry[]>`。 |
191
204
  | `portalTarget.value` | 弹层挂载 DOM 元素。 |
192
205
  | `motion.value.set(mode)` | 即时修改全局动效策略。 |
206
+ | `ripple.value.enabled / set(enabled)` | 全局点击波纹开关,默认 true;也可传入 `createAppleUI({ ripple: false })`。切换到减弱动效或系统开启减少动态效果时自动关闭,可手动开启;只有关闭动效时禁止开启。开启 persist 时保存偏好,嵌套 Provider 共享此开关。 |
193
207
  | `onMessage(channel,listener)` | 注册监听器,返回取消订阅函数。 |
194
208
  | `sendMessage(channel,payload?)` | 返回该 channel 全部监听器的返回值数组。 |
195
209
  | `dialog(options)` | 打开 dialog 并返回独立句柄。 |
@@ -0,0 +1,59 @@
1
+ # AppleInput API 页面样板
2
+
3
+ 当前验收入口:<http://127.0.0.1:5201/component-docs/apple-input>。也可以从组件总览的 AppleInput 卡片底部 AppleLink「代码与 API」进入。第一阶段只注册 AppleInput,未扩面、未提交、未发布,404 与已有工作保持原样。
4
+
5
+ ## 当前交互
6
+
7
+ - 独立页面,顶部使用 AppleBreadcrumbs;四边 padding 统一40px。顶部组件演示、左侧 AppleTree 列出全部属性、事件、插槽和方法,点击定位并高亮;支持键盘展开/折叠,不再显示单独的 API tab。总览入口与相邻展开栏的高度、字号、字重、颜色和padding一致。
8
+ - 17 条公开接口:11 个 props、3 个 events、2 个 slots、focus() 方法。均有源码核实的类型、默认值(适用时)、解释和行为边界。
9
+ - 示例按需提供。Vue 原生 v-model 与原生 placeholder 只解释,不另做专门示例;15 个组件相关例子通过 AppleAccordion 展开。
10
+ - 示例标题、功能和操作说明全部放在 Accordion 的展开内容内。
11
+ - 桌面左侧效果、右侧 Vue SFC;720px 以下上下排列。三项输入类型使用 AppleSegmentedControl;五项动效模式使用 AppleSelect,状态切换使用 AppleSwitch,示例容器使用 AppleCard,操作使用 AppleButton。
12
+ - API 文档按页面加载;编译器、CodeMirror、运行资源直到展开示例才加载。任意时刻只有一个编辑器与 iframe,折叠/切换销毁实例,草稿仅保存本页内代码文本,离开页面丢弃。恢复示例返回原始文本。
13
+ - 移除了组件源码编辑 tab。源码提取工具与可选 implementation 契约保留供后续确需源码的示例使用,当前页面不下载源码快照。
14
+
15
+ ## 可复用边界
16
+
17
+ `playground/editor/contract.ts` 定义 ComponentDocument:name/source、props/events/slots/methods/notes。ApiEntry 必须提供 id/name/type/description,default 与完整 SFC example 可选。不要为了填满页面给所有原生 API 制作重复示例。
18
+
19
+ `playground/editor/documents.ts` 是轻量注册表,每项提供名称、标签、分组、说明、异步文档 loader,以及可选预览组件。组件总览根据注册表自动显示文档入口;没有注册的组件保持原来的展开区。
20
+
21
+ `playground/views/component-docs/[component].vue` 是共用文件路由:根据 slug 读取注册表、加载文档、生成导航与演示。没有 AppleInput 的专属布局逻辑,也不依赖总览的 ComponentDemo/catalog。删除总览及其演示文件时,独立文档仍可构建。
22
+
23
+ `ComponentDocumentLink.vue` 只负责卡片底部 AppleLink 与 Vue Router 导航。`ComponentWorkshop.vue` 接收 doc prop,统一渲染 API、Accordion、单个活动示例和文本草稿。`LiveVueEditor.vue` 只接收 files、activeFile、baselineFiles,负责官方 REPL、主题、恢复/复制和错误显示。
24
+
25
+ 后续接入步骤:从组件真实源码列举接口 → 编写符合契约的文档和必要 SFC 例子 → 提供可选轻量预览 → 注册 slug。页面/入口/编辑器不需要复制或重写。当前注册表只含 AppleInput,待样板验收后再按组件分块实施。
26
+
27
+ ## 编译方案、依赖与资源
28
+
29
+ 使用 [Vue 官方 @vue/repl](https://github.com/vuejs/repl) 4.7.2、官方 CodeMirror、useStore/Sandbox/compiler-sfc。不自造正则编译器。用户代码在本地浏览器编译,不上传第三方。支持 template、script setup、普通 CSS/scoped CSS、响应式状态及组件库 ESM 导入。
30
+
31
+ [Vuetify Play](https://play.vuetifyjs.com/) 作为交互依据;已检查官方发布页面/入口,使用 Vue REPL 与异步 MonacoWrapper。本样板选择较轻的官方 CodeMirror,避免 Monaco 的额外 CDN 类型加载。
32
+
33
+ 开发依赖:固定 @vue/repl 4.7.2、es-module-shims ^2.8.4、esbuild ^0.25.12、postcss ^8.5.28;esbuild/PostCSS 原已作为传递依赖安装,现声明为构建工具直接依赖。未升级无关依赖,不加入组件库生产入口。
34
+
35
+ 当前生产 gzip 约:文档数据 4.8KB;共享路由 JS/CSS 3.8KB;展开时编辑器/compiler/CodeMirror JS 417.6KB、CSS 4.3KB;预览 Vue 41.9KB、Apptify runtime 79.6KB、库 CSS 16.2KB、shim 23KB。展开新增约583KB gzip。额外 TS/JSX 转换块约1.05MB gzip,仅相关语法触发时加载。下载缓存关闭后仍保留,运行实例销毁。
36
+
37
+ `tooling/playground-editor.mjs` 将本地库及依赖打包为浏览器 ESM,Vue 单独映射;消费者使用公开 apptify/apptify/style.css,不依赖仓库外路径。模板同步包含注册表、页面、共享编辑器、预览与文档数据。Vite dev/preview 自动给 assets/editor/* 添加公开资源 CORS;静态部署也需设置这些资源的 CORS。
38
+
39
+ ## 隔离与限制
40
+
41
+ 固定版本 REPL 的 sandbox 收紧为 allow-scripts,其余权限删除,上游结构变化时构建失败,未改官方编译器。opaque iframe 隔离父文档/存储及预览 CSS,普通编译/运行错误在编辑器中展示。CSP 默认禁止资源,允许 inline/blob/本机运行资源;不自动解析任意 npm、不请求 CDN。严格父 CSP 需要兼容 srcdoc、inline 模块与 blob;本样板不修改父服务器策略。
42
+
43
+ iframe 可能共享浏览器进程,同步死循环、超大编译输入、内存耗尽仍可能卡住标签页;刷新可恢复,不能承诺完全隔离。CSP 允许当前 origin 请求,不隔离同源 API 副作用,不运行不可信代码。无 Sass/Less、任意 npm 解析、服务端 API 与文件系统。
44
+
45
+ 真实表单导航被禁用;required 例子使用原生 reportValidity() 模拟提交校验。重新编译会 unmount 旧 Vue 应用,代码创建的资源须在 onUnmounted 清理;重新运行重建 iframe,折叠/离开销毁运行 realm。auto-resize=false 避免上游每次 mount 额外注册未清理的 resize handler;CodeMirror 自身一次性共享处理器保留。
46
+
47
+ 用户截图中的 import map 报错已修复:useStore 之前同步建立文件/map,以 App.vue 开始编译再切换活动文件,设置 welcomeSFC 防止官方默认欢迎页替换入口。恢复带完整 map 并串行应用。
48
+
49
+ ## 验证
50
+
51
+ `tests/e2e/input-workshop.spec.ts` 验证总览底部 AppleLink 导航、直接访问文档路由、无多余 tab、面包屑、40px padding、相邻底栏样式一致性、17 个接口/15 个 Accordion、展开前无编辑器/编译器资源、同一时间一个编辑器、每个例子的实际组件显示、代码修改、编译/运行错误恢复、清空、required/focus、草稿保留/恢复、反复运行、dark 主题、桌面左右/手机上下几何位置、390px 无溢出、折叠/离开销毁。最终生产回归14.6秒通过,pageErrors为空。文档页DOM:展开前441 → 展开764 → 折叠447;编辑器与iframe均为0 → 1 → 0。折叠后保留下载资源缓存。
52
+
53
+ 最新截图和原始 DOM/资源数据:`artifacts/input-workshop/api-page-desktop.png`、`api-page-mobile.png`、`metrics-v3.json`。早期弹窗证据保留为历史记录,不代表当前界面。
54
+
55
+ 类型检查、生产构建、消费者完整模板/删减模板与库消费验证通过;归档验证目录为`/var/folders/y3/wc0kb5h13yl41wyj6nrf3vv00000gp/T/apptify-package-9m8mVc`。早期全库单元测试179通过、1个既有404动画frames失败;按要求未修改该内容。
56
+
57
+ 所有接口与示例说明改用直白中文:先说明用途与操作,再解释必要的边界。树形导航和正文共用 sections.ts 分组契约,不需要逐页维护导航节点。
58
+
59
+ 预览动效跟随页面设置,并通过组件库上下文监听系统减少动效偏好。预览根节点应用与 AppleProvider 一致的公共样式和解析后的动效模式;卸载时停止偏好监听。Playwright 验证 full 模式下分段切换存在实际动画,none 模式下没有运行中的动画。