apptify 0.2.0 → 0.5.1
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/README.md +40 -239
- package/dist/apptify.css +1 -1
- package/dist/apptify.js +4153 -2177
- package/dist/components/button.d.ts +1 -1
- package/dist/components/content.d.ts +73 -362
- package/dist/components/date-picker.d.ts +10 -0
- package/dist/components/forms.d.ts +77 -18
- package/dist/components/foundation.d.ts +2061 -111
- package/dist/components/gallery-scrollbar.d.ts +46 -0
- package/dist/components/mobile-image-viewer.d.ts +166 -0
- package/dist/components/navibar.d.ts +80 -0
- package/dist/components/overlays.d.ts +127 -158
- package/dist/components/tabs.d.ts +117 -0
- package/dist/core/context.d.ts +573 -9
- package/dist/core/desktop-image-enter.d.ts +6 -0
- package/dist/core/desktop-image-return.d.ts +1 -0
- package/dist/core/device.d.ts +5 -0
- package/dist/core/image-gallery-motion.d.ts +2 -0
- package/dist/core/image-geometry.d.ts +28 -0
- package/dist/core/image-motion.d.ts +18 -0
- package/dist/core/layers.d.ts +2 -0
- package/dist/core/motion.d.ts +2 -0
- package/dist/core/popup-motion.d.ts +12 -0
- package/dist/core/popup-placement.d.ts +31 -0
- package/dist/core/preview-navigation.d.ts +5 -0
- package/dist/index.d.ts +1214 -339
- package/docs/COMPONENTS.md +18 -16
- package/docs/PLAYGROUND-TEMPLATE.md +51 -0
- package/docs/VALIDATION.md +25 -1
- package/package.json +35 -7
- package/templates/playground/README.md +21 -0
- package/templates/playground/gitignore +3 -0
- package/templates/playground/index.html +26 -0
- package/templates/playground/package.json +26 -0
- package/templates/playground/playground/App.vue +73 -0
- package/templates/playground/playground/ComponentDemo.vue +234 -0
- package/templates/playground/playground/catalog.ts +80 -0
- package/templates/playground/playground/components/ComponentIndex.vue +62 -0
- package/templates/playground/playground/components/PageFooter.vue +3 -0
- package/templates/playground/playground/components/UserMenu.vue +132 -0
- package/templates/playground/playground/components/not-found-paper-scene.vue +210 -0
- package/templates/playground/playground/components/not-found-paper-story.ts +149 -0
- package/templates/playground/playground/env.d.ts +1 -0
- package/templates/playground/playground/main.ts +8 -0
- package/templates/playground/playground/router/index.ts +24 -0
- package/templates/playground/playground/style.css +228 -0
- package/templates/playground/playground/views/[...all].vue +68 -0
- package/templates/playground/playground/views/components.vue +126 -0
- package/templates/playground/playground/views/index.vue +75 -0
- package/templates/playground/playground/views/settings.vue +98 -0
- package/templates/playground/public/images/SOURCES.md +21 -0
- package/templates/playground/public/images/airpods-max-orange.jpg +0 -0
- package/templates/playground/public/images/architecture.jpg +0 -0
- package/templates/playground/public/images/city.jpg +0 -0
- package/templates/playground/public/images/coast.jpg +0 -0
- package/templates/playground/public/images/desert.jpg +0 -0
- package/templates/playground/public/images/food.jpg +0 -0
- package/templates/playground/public/images/forest.jpg +0 -0
- package/templates/playground/public/images/lake.jpg +0 -0
- package/templates/playground/public/images/mountains.jpg +0 -0
- package/templates/playground/public/images/snow.jpg +0 -0
- package/templates/playground/public/images/sunset.jpg +0 -0
- package/templates/playground/public/images/waterfall.jpg +0 -0
- package/templates/playground/source-snapshot.json +111 -0
- package/templates/playground/tsconfig.json +24 -0
- package/templates/playground/vite.config.ts +9 -0
- package/tooling/create-playground.mjs +35 -0
- package/tooling/prepare-package.mjs +35 -0
- package/tooling/prepare-playground.mjs +103 -0
- package/tooling/test-create-apptify.mjs +76 -0
- package/tooling/test-playground-package.mjs +188 -0
- package/tooling/vite.d.ts +5 -0
- package/tooling/vite.js +10 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Demo image sources
|
|
2
|
+
|
|
3
|
+
These images are preview fixtures, not part of the npm library output.
|
|
4
|
+
|
|
5
|
+
- `airpods-max-orange.jpg`: Apple official store CDN, https://store.storeimages.cdn-apple.com/1/as-images.apple.com/is/airpods-max-select-202409-orange?wid=800&hei=800&fmt=jpeg&qlt=85 . Product imagery belongs to Apple; replace with your own licensed assets for production distribution. This project is not affiliated with Apple.
|
|
6
|
+
- `lake.jpg`: Unsplash, https://images.unsplash.com/photo-1470770841072-f978cf4d019e?auto=format&fit=crop&w=1200&q=85 . Demo landscape photo, retrieved 2026-09-26.
|
|
7
|
+
|
|
8
|
+
Design references: https://www.apple.com/store/ and https://vuetifyjs.com/en/directives/ripple/ . No Apple fonts are bundled; system fonts are used.
|
|
9
|
+
|
|
10
|
+
Additional AppleImage demo photos, retrieved 2026-10-02:
|
|
11
|
+
|
|
12
|
+
- `mountains.jpg`: Unsplash, https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&w=1000&q=80 .
|
|
13
|
+
- `forest.jpg`: Unsplash, https://images.unsplash.com/photo-1441974231531-c6227db76b6e?auto=format&fit=crop&w=800&h=1200&q=80 .
|
|
14
|
+
- `coast.jpg`: Unsplash, https://images.unsplash.com/photo-1473116763249-2faaef81ccda?auto=format&fit=crop&w=1600&h=600&q=80 .
|
|
15
|
+
- `desert.jpg`: Unsplash, https://images.unsplash.com/photo-1509316785289-025f5b846b35?auto=format&fit=crop&w=1000&h=750&q=80 .
|
|
16
|
+
- `waterfall.jpg`: Unsplash, https://images.unsplash.com/photo-1432405972618-c60b0225b8f9?auto=format&fit=crop&w=700&h=1400&q=80 .
|
|
17
|
+
- `sunset.jpg`: Unsplash, https://images.unsplash.com/photo-1472120435266-53107fd0c44a?auto=format&fit=crop&w=1200&h=500&q=80 .
|
|
18
|
+
- `snow.jpg`: Unsplash, https://images.unsplash.com/photo-1418985991508-e47386d96a71?auto=format&fit=crop&w=900&h=1100&q=80 .
|
|
19
|
+
- `city.jpg`: Unsplash, https://images.unsplash.com/photo-1480714378408-67cf0d13bc1b?auto=format&fit=crop&w=800&h=1000&q=80 .
|
|
20
|
+
- `architecture.jpg`: Unsplash, https://images.unsplash.com/photo-1511818966892-d7d671e672a2?auto=format&fit=crop&w=700&h=1200&q=80 .
|
|
21
|
+
- `food.jpg`: Unsplash, https://images.unsplash.com/photo-1504674900247-0877df9cc836?auto=format&fit=crop&w=1000&h=800&q=80 .
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-10-03T07:22:12.858Z",
|
|
3
|
+
"libraryVersion": "0.5.1",
|
|
4
|
+
"files": {
|
|
5
|
+
"index.html": "75f6d93e3962ddca97a13b666a04d98ba9b263b6c288171383db764215034fea",
|
|
6
|
+
"playground/App.vue": "ef3f06f80758a3d4198ee90eb05f766a89b6156b4899fd566f8dca9b42e0ffc9",
|
|
7
|
+
"playground/ComponentDemo.vue": "0801a9eba5aa2e06f3bbd972b25647fed145ee6d630fd4d183eb016862f25ad4",
|
|
8
|
+
"playground/catalog.ts": "80b10ca45b18a611baec19361c70a967da655690c04091d23541192cd02fcecd",
|
|
9
|
+
"playground/components/ComponentIndex.vue": "2223f76786ef3dd1658fbb1ce29246e9bd155343d2e9bea9cb0674bc4a4ef879",
|
|
10
|
+
"playground/components/PageFooter.vue": "29c3ae396450c961aa13f3edc7d6b15f9dd12e95033242328fbe2093fb5ff0eb",
|
|
11
|
+
"playground/components/UserMenu.vue": "e584cc4c97c8e5a582be259f5aafc0ac355f4339133f6f572f079d979aa96c10",
|
|
12
|
+
"playground/components/not-found-paper-scene.vue": "39f12c23f04d72131d9da51e9a960894b621f2581c25e5b18463f7b458127209",
|
|
13
|
+
"playground/components/not-found-paper-story.ts": "b7c02528ce58080662f0e55bc4a6b11c170fc987b3b5e377ff7c0db8f77ddf10",
|
|
14
|
+
"playground/env.d.ts": "daae3800510e936d8308b7a9ebb0cb28d8f3fcd449e41386feea05d29bd12540",
|
|
15
|
+
"playground/main.ts": "efa30fb81f5c5f46ca21dc32a96fb08b32665b2d7de9d426e52c617662203285",
|
|
16
|
+
"playground/router/index.ts": "fe5f1c4b53f2f636bcb25727013b5cfb1e96bcadfd7f1a841537583fc98eccf5",
|
|
17
|
+
"playground/style.css": "940d33a07191f6143b1aef319bf7d09db479d2c0b3b3f6743a4362f8ea9c9e8b",
|
|
18
|
+
"playground/views/[...all].vue": "6d1cd2b7a67cc9e2b2935555633cda148dd81b5ca441bcb9b43029b8f719d3f9",
|
|
19
|
+
"playground/views/components.vue": "5edb34d2100f192d18fb7789a188b880c26daccad9597fe68d319927ac14e15a",
|
|
20
|
+
"playground/views/index.vue": "703fc1a39c31aaff17c8f6c69f418d455b9a16af5bb1b977403d77b09ef3f1e4",
|
|
21
|
+
"playground/views/settings.vue": "43e1074d8a17104ad88f72e7c7787a390b76e7948fa321b1c667e7ba41c9cae6",
|
|
22
|
+
"public/images/SOURCES.md": "24ccb6625b1168e48550b7651e9fc20cb747324d87666d39199608c7db20541b",
|
|
23
|
+
"public/images/airpods-max-orange.jpg": "f365fe9e374e2cede88f3e68487f6a773a767873978bcf20e4b21dee08aca966",
|
|
24
|
+
"public/images/architecture.jpg": "928ea321954f0edabc1eed3c908c6b1fc93b247badcbd89d8dc5ba237420c26b",
|
|
25
|
+
"public/images/city.jpg": "2ff983f15a2116a169e0a77e841e546848951185d0be4cf1ba8983c350c05109",
|
|
26
|
+
"public/images/coast.jpg": "20fe6b79672be065307c3eed01d6a067969489c79baec35020a14a8f4cdecb3e",
|
|
27
|
+
"public/images/desert.jpg": "f2bcb6ee381cae278a29e89c3e1ea066bd34e885a0d3c08e856f994156cb546e",
|
|
28
|
+
"public/images/food.jpg": "9a36b1dacff2b9e7a1ebcdb14be714c17ee2d15d61de043faf178d5473753553",
|
|
29
|
+
"public/images/forest.jpg": "f57adf0b41247970af93cb4897fdfdf4bfe4f2004319ff905c912a419a43a1f6",
|
|
30
|
+
"public/images/lake.jpg": "26f1167b6c07e4d67cd90c469390ebb310bfa082a7d86e0e3758f616176378c7",
|
|
31
|
+
"public/images/mountains.jpg": "57aae81c2886f3404c582dd637ed325559616621466c027d2d1039bd918a213a",
|
|
32
|
+
"public/images/snow.jpg": "59fec6d2bbf9df11b7c697c57a253b7bd4b5a097489ce1017fb5209b9ee54b8e",
|
|
33
|
+
"public/images/sunset.jpg": "4ee91e88f1e341143a807ef48fdfc24d63aa045d99351b4ea8ad7efcfef6ef9b",
|
|
34
|
+
"public/images/waterfall.jpg": "cfd55ff5f41d3a58e91793d0e26a9ca90c86760aa401da033fbfa77d3364f238"
|
|
35
|
+
},
|
|
36
|
+
"buildSources": {
|
|
37
|
+
"src/components/button.ts": "45db9f1488643ea03e6af5a090d6811fd815993f6ad5a5801cd9227394224439",
|
|
38
|
+
"src/components/content.ts": "e2206c834004ee7e099b2b9b4d7afe14b55a18c89569291ce44bc9a472d70f98",
|
|
39
|
+
"src/components/date-picker.ts": "130c127d4ab736e633b7eeaea5e9aa8937783391c690fe10479d90256b6930bd",
|
|
40
|
+
"src/components/forms.ts": "18cc26a711283a221c712e3c68791b5d1943240b954ca47b0a8525ae0c8598c5",
|
|
41
|
+
"src/components/foundation.ts": "671c6aa20cd2a253483f26d290a0080dba43c2656ae470dd5a84755a729bd1a4",
|
|
42
|
+
"src/components/gallery-scrollbar.ts": "3763c0f05629fed9d8b82514339f768d305120b56308f8ae8a9460c9853719bb",
|
|
43
|
+
"src/components/mobile-image-viewer.ts": "66cecdf485a731c231823d1137cffc26c92cde45d94ef8def5b0bff070de48f4",
|
|
44
|
+
"src/components/motion.ts": "d294cc879e690e07358765e33e318cd4f427b17ac66cb5f1bf5848c9fc453419",
|
|
45
|
+
"src/components/navibar.ts": "01c58cc6563273006ae91c43853283f60499de9fc88ba3a072ca64ef07f7eb2c",
|
|
46
|
+
"src/components/overlays.ts": "840bb7b1620d05beae767a2d6af9493f4e0dade8c098517d4260ca644221f3ba",
|
|
47
|
+
"src/components/tabs.ts": "a80fdf41efff49c2870859d6c0a97e5bbba69055706309acd5b53eafe8c02f9d",
|
|
48
|
+
"src/core/context.ts": "c96ccc6e75ac53b9461730dd61dd79952ca23004f08b1f9d199ca6478034fe4e",
|
|
49
|
+
"src/core/desktop-image-enter.ts": "6852f1a0a5d6cccfbe50509934729fea9e82ccd4c0cf9bdeda629eed2d9e3ef0",
|
|
50
|
+
"src/core/desktop-image-return.ts": "cfb4e9fc6cea3cd8dd614b940345e5314b6e74f4748c6066ab1cc6b4c535fe08",
|
|
51
|
+
"src/core/device.ts": "da97e64aa1a041d88c77818a836cee0e2401fb73a532bc173c2e19fa471ca97f",
|
|
52
|
+
"src/core/image-gallery-motion.ts": "0eab74e68687a930fa2501e7d23a63e83f0124bc5d9da55be541817f40ee2a33",
|
|
53
|
+
"src/core/image-geometry.ts": "6eb4d4e2a2afd078ccce010ec8aae32d89bf70a1e8c2c522b5e81040a97a1037",
|
|
54
|
+
"src/core/image-motion.ts": "da1eded52a297332d314c9c1e27dc34ce031e07b6acce147ab2ae6eb9d7895d5",
|
|
55
|
+
"src/core/layers.ts": "fe15fa50c82155e894f2e42a80340bd61bda2cfa4d3e9646a69f556c49fc5b04",
|
|
56
|
+
"src/core/motion.ts": "cb8b0cce9f4343cfc927466e21c3a315cf99df1e23380bfa10937b4caea62514",
|
|
57
|
+
"src/core/popup-motion.ts": "528f3a0d95eea5e63c4c2732b247eb71824c9fafc4d3a822b03d180a29902924",
|
|
58
|
+
"src/core/popup-placement.ts": "605138db77d9e1ebb9433281533ea607d9cead7689c6ea2596a9b20a277251d3",
|
|
59
|
+
"src/core/preview-navigation.ts": "8de5cc0f62b16b0590f212de6f7bb234859ec483a612673a87dd8fe9e260a813",
|
|
60
|
+
"src/index.ts": "75e2a540a1310aeda2e2eb64ffd8e1c93f83f2fab915f8f73432c4f554a67d55",
|
|
61
|
+
"src/styles/base.css": "02973e340575383182b378daabdbafcd7bc1e1191aea829ba11dc41010854547",
|
|
62
|
+
"src/styles/content.css": "3a57b7f24f5edb0245e8edba463f4a4fd5bd46fbe515d3332ba4eb708c4fb6f0",
|
|
63
|
+
"src/styles/date-picker.css": "a64396f52b95df206bca5c5a6f5d68777bc0b9426d08664998be23694727b2d7",
|
|
64
|
+
"src/styles/forms.css": "156dc5e5d43020abf3ca56f1d0b9898d4bf57e4a00588f6a764f69939b66b57b",
|
|
65
|
+
"src/styles/navibar.css": "56bf34300e3064e42cb0a0d35a2d6d4cc7ff5ba69740a6d1d6af55397fc555d6",
|
|
66
|
+
"src/styles/overlays.css": "7b975aa8b6796a9b2e051555807e834a399430397b8b8395c0b6b35af034d0ef",
|
|
67
|
+
"src/styles/ripple.css": "df0a5f661a862b5232bac256958f4bae6f555dd1f4a9c1432f61e85de71bdfea",
|
|
68
|
+
"playground/App.vue": "ef3f06f80758a3d4198ee90eb05f766a89b6156b4899fd566f8dca9b42e0ffc9",
|
|
69
|
+
"playground/ComponentDemo.vue": "0801a9eba5aa2e06f3bbd972b25647fed145ee6d630fd4d183eb016862f25ad4",
|
|
70
|
+
"playground/catalog.ts": "80b10ca45b18a611baec19361c70a967da655690c04091d23541192cd02fcecd",
|
|
71
|
+
"playground/components/ComponentIndex.vue": "2223f76786ef3dd1658fbb1ce29246e9bd155343d2e9bea9cb0674bc4a4ef879",
|
|
72
|
+
"playground/components/PageFooter.vue": "29c3ae396450c961aa13f3edc7d6b15f9dd12e95033242328fbe2093fb5ff0eb",
|
|
73
|
+
"playground/components/UserMenu.vue": "e584cc4c97c8e5a582be259f5aafc0ac355f4339133f6f572f079d979aa96c10",
|
|
74
|
+
"playground/components/not-found-paper-scene.vue": "39f12c23f04d72131d9da51e9a960894b621f2581c25e5b18463f7b458127209",
|
|
75
|
+
"playground/components/not-found-paper-story.ts": "b7c02528ce58080662f0e55bc4a6b11c170fc987b3b5e377ff7c0db8f77ddf10",
|
|
76
|
+
"playground/env.d.ts": "daae3800510e936d8308b7a9ebb0cb28d8f3fcd449e41386feea05d29bd12540",
|
|
77
|
+
"playground/main.ts": "efa30fb81f5c5f46ca21dc32a96fb08b32665b2d7de9d426e52c617662203285",
|
|
78
|
+
"playground/router/index.ts": "fe5f1c4b53f2f636bcb25727013b5cfb1e96bcadfd7f1a841537583fc98eccf5",
|
|
79
|
+
"playground/style.css": "940d33a07191f6143b1aef319bf7d09db479d2c0b3b3f6743a4362f8ea9c9e8b",
|
|
80
|
+
"playground/views/[...all].vue": "6d1cd2b7a67cc9e2b2935555633cda148dd81b5ca441bcb9b43029b8f719d3f9",
|
|
81
|
+
"playground/views/components.vue": "5edb34d2100f192d18fb7789a188b880c26daccad9597fe68d319927ac14e15a",
|
|
82
|
+
"playground/views/index.vue": "703fc1a39c31aaff17c8f6c69f418d455b9a16af5bb1b977403d77b09ef3f1e4",
|
|
83
|
+
"playground/views/settings.vue": "43e1074d8a17104ad88f72e7c7787a390b76e7948fa321b1c667e7ba41c9cae6",
|
|
84
|
+
"public/images/SOURCES.md": "24ccb6625b1168e48550b7651e9fc20cb747324d87666d39199608c7db20541b",
|
|
85
|
+
"public/images/airpods-max-orange.jpg": "f365fe9e374e2cede88f3e68487f6a773a767873978bcf20e4b21dee08aca966",
|
|
86
|
+
"public/images/architecture.jpg": "928ea321954f0edabc1eed3c908c6b1fc93b247badcbd89d8dc5ba237420c26b",
|
|
87
|
+
"public/images/city.jpg": "2ff983f15a2116a169e0a77e841e546848951185d0be4cf1ba8983c350c05109",
|
|
88
|
+
"public/images/coast.jpg": "20fe6b79672be065307c3eed01d6a067969489c79baec35020a14a8f4cdecb3e",
|
|
89
|
+
"public/images/desert.jpg": "f2bcb6ee381cae278a29e89c3e1ea066bd34e885a0d3c08e856f994156cb546e",
|
|
90
|
+
"public/images/food.jpg": "9a36b1dacff2b9e7a1ebcdb14be714c17ee2d15d61de043faf178d5473753553",
|
|
91
|
+
"public/images/forest.jpg": "f57adf0b41247970af93cb4897fdfdf4bfe4f2004319ff905c912a419a43a1f6",
|
|
92
|
+
"public/images/lake.jpg": "26f1167b6c07e4d67cd90c469390ebb310bfa082a7d86e0e3758f616176378c7",
|
|
93
|
+
"public/images/mountains.jpg": "57aae81c2886f3404c582dd637ed325559616621466c027d2d1039bd918a213a",
|
|
94
|
+
"public/images/snow.jpg": "59fec6d2bbf9df11b7c697c57a253b7bd4b5a097489ce1017fb5209b9ee54b8e",
|
|
95
|
+
"public/images/sunset.jpg": "4ee91e88f1e341143a807ef48fdfc24d63aa045d99351b4ea8ad7efcfef6ef9b",
|
|
96
|
+
"public/images/waterfall.jpg": "cfd55ff5f41d3a58e91793d0e26a9ca90c86760aa401da033fbfa77d3364f238",
|
|
97
|
+
"docs/COMPONENTS.md": "975f33ddb8584c0cb2a12066316018a02a7bfd73014a0a79d89d8990ca06f496",
|
|
98
|
+
"docs/PLAYGROUND-TEMPLATE.md": "26b15d5d9ca939d765aa93ce1389018f1aa4ce32de11c368556344b81c6b8b09",
|
|
99
|
+
"docs/VALIDATION.md": "3c1755f4699d6b7d8febb44b2b0b00eb416b86559c26d8b69e46a1c98271af5f",
|
|
100
|
+
"README.md": "7923e6dd7f06996af0ac8fcafafc9c338f5700969fd080a8af31a08df9514e58",
|
|
101
|
+
"package.json": "ceb8c42a9140d21fa2d4dd20528a85922be94d99ad739aeec83519b471092a86",
|
|
102
|
+
"index.html": "75f6d93e3962ddca97a13b666a04d98ba9b263b6c288171383db764215034fea",
|
|
103
|
+
"vite.config.ts": "df2eae92f81c9b9007549de5721a2311dd9b918dea45a4c7b8b4979f247e49ae",
|
|
104
|
+
"vite.lib.config.ts": "f877c1772da70c9fed5174118ca36a0fc25fd46cce49b71280a5f91c4f8003a3",
|
|
105
|
+
"tsconfig.json": "09590870bfbf6e90614d8a34af38b9a72902e8747ecd1a76be47ab24c842f9ea",
|
|
106
|
+
"tsconfig.lib.json": "c885806b003cee01192cddcaf32df3e7c6d369e645360398aa088c14b1c4792f",
|
|
107
|
+
"tooling/create-playground.mjs": "c45480c5982a64efd06f69dfb4620c65fd8ea35d01877b8574e7e2b30c095606",
|
|
108
|
+
"tooling/prepare-playground.mjs": "2e431ee93803d640f9b81fd8228a6b2edf0538e0eef8a8749f0622abf9f1a23e",
|
|
109
|
+
"tooling/prepare-package.mjs": "cf57a112eec798412e2a68089d1b2d25b984600d6ffef99397ec253abf2fca57"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"jsx": "preserve",
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"lib": [
|
|
11
|
+
"ES2022",
|
|
12
|
+
"DOM",
|
|
13
|
+
"DOM.Iterable"
|
|
14
|
+
],
|
|
15
|
+
"skipLibCheck": true,
|
|
16
|
+
"types": [
|
|
17
|
+
"vite/client"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"include": [
|
|
21
|
+
"playground/**/*.ts",
|
|
22
|
+
"playground/**/*.vue"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import vue from '@vitejs/plugin-vue'
|
|
3
|
+
import apptifyRoutes from 'apptify/vite'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [apptifyRoutes({ dirs: [{ dir: 'playground/views', baseRoute: '' }] }), vue()],
|
|
7
|
+
server: { host: '127.0.0.1' },
|
|
8
|
+
build: { outDir: 'dist' },
|
|
9
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cp, mkdir, readFile, readdir, rename, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { resolve, join, sep } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { execFileSync } from 'node:child_process'
|
|
6
|
+
|
|
7
|
+
const root = fileURLToPath(new URL('../', import.meta.url))
|
|
8
|
+
const destination = process.argv[2]
|
|
9
|
+
if (!destination || ['--help', '-h'].includes(destination)) {
|
|
10
|
+
console.log('Usage: apptify-playground <empty-directory>\nCopies the complete editable playground and a portable local library archive.\nThen run npm install and npm run dev in that directory.')
|
|
11
|
+
process.exit(destination ? 0 : 1)
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const target = resolve(destination)
|
|
15
|
+
const packageRoot = resolve(root)
|
|
16
|
+
if (target === packageRoot || target.startsWith(packageRoot + sep)) throw new Error('Destination must be outside the installed apptify package')
|
|
17
|
+
const existing = await readdir(target).catch(error => { if (error.code === 'ENOENT') return []; throw error })
|
|
18
|
+
if (existing.length) throw new Error('Destination must be empty: ' + target)
|
|
19
|
+
const template = join(root, 'templates/playground')
|
|
20
|
+
await readFile(join(template, 'package.json'))
|
|
21
|
+
await mkdir(target, { recursive: true })
|
|
22
|
+
await cp(template, target, { recursive: true })
|
|
23
|
+
await rename(join(target, 'gitignore'), join(target, '.gitignore'))
|
|
24
|
+
const vendor = join(target, 'vendor')
|
|
25
|
+
await mkdir(vendor)
|
|
26
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
27
|
+
const packed = JSON.parse(execFileSync(npm, ['pack', '--ignore-scripts', '--json', '--loglevel=error', '--pack-destination', vendor], { cwd: root, encoding: 'utf8' }))
|
|
28
|
+
const manifest = JSON.parse(await readFile(join(target, 'package.json'), 'utf8'))
|
|
29
|
+
manifest.dependencies.apptify = 'file:./vendor/' + packed[0].filename
|
|
30
|
+
await writeFile(join(target, 'package.json'), JSON.stringify(manifest, null, 2) + '\n')
|
|
31
|
+
console.log('Created ' + target + '\nNext: cd ' + JSON.stringify(target) + ' && npm install && npm run dev')
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error(error.message)
|
|
34
|
+
process.exitCode = 1
|
|
35
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { readFile, readdir, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { join, relative } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { createHash } from 'node:crypto'
|
|
6
|
+
import { execFileSync } from 'node:child_process'
|
|
7
|
+
|
|
8
|
+
const root = fileURLToPath(new URL('../', import.meta.url))
|
|
9
|
+
async function sourceHashes() {
|
|
10
|
+
const files = {}
|
|
11
|
+
const record = async path => {
|
|
12
|
+
files[relative(root, path).replaceAll('\\', '/')] = createHash('sha256').update(await readFile(path)).digest('hex')
|
|
13
|
+
}
|
|
14
|
+
const directory = async path => {
|
|
15
|
+
for (const entry of await readdir(path, { withFileTypes: true })) {
|
|
16
|
+
if (entry.name === '.DS_Store') continue
|
|
17
|
+
const child = join(path, entry.name)
|
|
18
|
+
if (entry.isDirectory()) await directory(child)
|
|
19
|
+
else await record(child)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (const name of ['src', 'playground', 'public', 'docs']) await directory(join(root, name))
|
|
23
|
+
for (const name of ['README.md', 'package.json', 'index.html', 'vite.config.ts', 'vite.lib.config.ts', 'tsconfig.json', 'tsconfig.lib.json', 'tooling/create-playground.mjs', 'tooling/prepare-playground.mjs', 'tooling/prepare-package.mjs']) await record(join(root, name))
|
|
24
|
+
return files
|
|
25
|
+
}
|
|
26
|
+
const before = await sourceHashes()
|
|
27
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
28
|
+
execFileSync(npm, ['run', 'build'], { cwd: root, stdio: 'inherit' })
|
|
29
|
+
execFileSync(process.execPath, [join(root, 'tooling/prepare-playground.mjs')], { cwd: root, stdio: 'inherit' })
|
|
30
|
+
assert.deepEqual(await sourceHashes(), before, 'Sources changed during the build; rerun packing to take the latest snapshot. No source file was restored.')
|
|
31
|
+
const snapshotPath = join(root, 'templates/playground/source-snapshot.json')
|
|
32
|
+
const snapshot = JSON.parse(await readFile(snapshotPath, 'utf8'))
|
|
33
|
+
snapshot.buildSources = before
|
|
34
|
+
await writeFile(snapshotPath, JSON.stringify(snapshot, null, 2) + '\n')
|
|
35
|
+
console.log('Library build and editable template share the same source snapshot.')
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { cp, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { basename, join, relative } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { createHash } from 'node:crypto'
|
|
5
|
+
|
|
6
|
+
const root = fileURLToPath(new URL('../', import.meta.url))
|
|
7
|
+
const output = join(root, 'templates/playground')
|
|
8
|
+
const library = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'))
|
|
9
|
+
await rm(output, { recursive: true, force: true })
|
|
10
|
+
await mkdir(output, { recursive: true })
|
|
11
|
+
const copyOptions = { recursive: true, filter: source => basename(source) !== '.DS_Store' }
|
|
12
|
+
await cp(join(root, 'playground'), join(output, 'playground'), copyOptions)
|
|
13
|
+
await cp(join(root, 'public'), join(output, 'public'), copyOptions)
|
|
14
|
+
await cp(join(root, 'index.html'), join(output, 'index.html'))
|
|
15
|
+
|
|
16
|
+
const snapshot = { createdAt: new Date().toISOString(), libraryVersion: library.version, files: {} }
|
|
17
|
+
async function record(directory) {
|
|
18
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
19
|
+
const path = join(directory, entry.name)
|
|
20
|
+
if (entry.isDirectory()) await record(path)
|
|
21
|
+
else snapshot.files[relative(output, path)] = createHash('sha256').update(await readFile(path)).digest('hex')
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
await record(output)
|
|
25
|
+
await writeFile(join(output, 'source-snapshot.json'), JSON.stringify(snapshot, null, 2) + '\n')
|
|
26
|
+
|
|
27
|
+
async function adapt(directory) {
|
|
28
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
29
|
+
const path = join(directory, entry.name)
|
|
30
|
+
if (entry.isDirectory()) await adapt(path)
|
|
31
|
+
else if (/\.(vue|ts)$/.test(entry.name)) {
|
|
32
|
+
let source = await readFile(path, 'utf8')
|
|
33
|
+
source = source.replace(/(['"])(?:\.\.\/)+src(?:\/(?:index|core\/motion|core\/context|components\/content))?\1/g, "'apptify'")
|
|
34
|
+
if (/(['"])(?:\.\.\/)+src(?:\/[^'"]*)?\1/.test(source)) throw new Error('Unmapped private library import: ' + path)
|
|
35
|
+
if (entry.name === 'main.ts') source = "import 'apptify/style.css'\n" + source
|
|
36
|
+
if (path === join(output, 'playground/App.vue')) {
|
|
37
|
+
const navigationEnd = ']\n\nfunction navigate'
|
|
38
|
+
if (!source.includes(navigationEnd)) throw new Error('App navigation layout changed; update template adaptation')
|
|
39
|
+
source = source.replace('to="/" aria-label="Apptify 首页"', ':to="homePath" aria-label="Apptify 首页"')
|
|
40
|
+
source = source.replace(navigationEnd, "].filter(item => router.getRoutes().some(page => page.path === item.href))\nconst homePath = navigation[0]?.href ?? '/'\n\nfunction navigate")
|
|
41
|
+
}
|
|
42
|
+
if (path === join(output, 'playground/views/[...all].vue')) {
|
|
43
|
+
source = source.replace('to="/" custom', ':to="homePath" custom')
|
|
44
|
+
source = source.replace('const router = useRouter()', "const router = useRouter()\nconst homePath = router.getRoutes().some(page => page.path === '/') ? '/' : '/settings'")
|
|
45
|
+
source = source.replace("else void router.push('/')", 'else void router.push(homePath)')
|
|
46
|
+
}
|
|
47
|
+
await writeFile(path, source)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
await adapt(join(output, 'playground'))
|
|
52
|
+
const manifest = {
|
|
53
|
+
name: 'apptify-app', version: '0.0.0', private: true, type: 'module',
|
|
54
|
+
scripts: { dev: 'vite', typecheck: 'vue-tsc --noEmit', build: 'vue-tsc --noEmit && vite build', preview: 'vite preview --host 127.0.0.1' },
|
|
55
|
+
dependencies: {
|
|
56
|
+
apptify: '^' + library.version, vue: library.peerDependencies.vue,
|
|
57
|
+
'vue-router': library.devDependencies['vue-router'], vuetify: library.peerDependencies.vuetify,
|
|
58
|
+
'lucide-vue-next': library.dependencies['lucide-vue-next'],
|
|
59
|
+
},
|
|
60
|
+
devDependencies: Object.fromEntries(['@vitejs/plugin-vue', 'typescript', 'vite', 'vite-plugin-pages', 'vue-tsc'].map(name => [name, library.devDependencies[name]])),
|
|
61
|
+
}
|
|
62
|
+
await writeFile(join(output, 'package.json'), JSON.stringify(manifest, null, 2) + '\n')
|
|
63
|
+
const tsconfig = JSON.parse(await readFile(join(root, 'tsconfig.json'), 'utf8'))
|
|
64
|
+
tsconfig.include = ['playground/**/*.ts', 'playground/**/*.vue']
|
|
65
|
+
await writeFile(join(output, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2) + '\n')
|
|
66
|
+
await writeFile(join(output, 'vite.config.ts'), [
|
|
67
|
+
"import { defineConfig } from 'vite'",
|
|
68
|
+
"import vue from '@vitejs/plugin-vue'",
|
|
69
|
+
"import apptifyRoutes from 'apptify/vite'",
|
|
70
|
+
'',
|
|
71
|
+
'export default defineConfig({',
|
|
72
|
+
" plugins: [apptifyRoutes({ dirs: [{ dir: 'playground/views', baseRoute: '' }] }), vue()],",
|
|
73
|
+
" server: { host: '127.0.0.1' },",
|
|
74
|
+
" build: { outDir: 'dist' },",
|
|
75
|
+
'})', '',
|
|
76
|
+
].join('\n'))
|
|
77
|
+
// npm excludes .gitignore from tarballs; the copy command restores its dot.
|
|
78
|
+
await writeFile(join(output, 'gitignore'), 'node_modules/\ndist/\n.env.local\n')
|
|
79
|
+
await writeFile(join(output, 'README.md'), [
|
|
80
|
+
"# Apptify 应用模板",
|
|
81
|
+
"",
|
|
82
|
+
"可编辑的 Vue 应用,包含导航、账号表单、外观设置、404 与组件示例。建议 Node.js 22 或 24 LTS。",
|
|
83
|
+
"",
|
|
84
|
+
"```sh",
|
|
85
|
+
"npm install",
|
|
86
|
+
"npm run dev",
|
|
87
|
+
"```",
|
|
88
|
+
"",
|
|
89
|
+
"检查:`npm run typecheck`、`npm run build`。",
|
|
90
|
+
"",
|
|
91
|
+
"- 页面:`playground/views/`,文件路由自动生成。",
|
|
92
|
+
"- 布局与导航:`playground/App.vue` 的 `navigation` 数组。",
|
|
93
|
+
"- 账号表单:`playground/components/UserMenu.vue`,需要接入自己的后端。",
|
|
94
|
+
"- 样式:`playground/style.css`;图片与来源:`public/images/`。",
|
|
95
|
+
"",
|
|
96
|
+
"可删除 `views/index.vue` 和 `views/components.vue`,再添加业务页面;删除后重启开发服务。删除组件总览后,可一并删除 `ComponentDemo.vue`、`catalog.ts` 和 `components/ComponentIndex.vue`。",
|
|
97
|
+
"",
|
|
98
|
+
"复制命令在 `vendor/` 保存库归档,移动整个项目后仍可独立安装。使用 npm 更新库:`npm install apptify@latest`。手工复制模板时,将 `gitignore` 重命名为 `.gitignore`。",
|
|
99
|
+
"",
|
|
100
|
+
"部署时将页面请求回退到 `index.html`,保留 API 与静态资源路由。",
|
|
101
|
+
"",
|
|
102
|
+
].join('\n'))
|
|
103
|
+
console.log('Prepared editable playground template: ' + output)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { mkdir, mkdtemp, readFile, rm, symlink, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
import { tmpdir } from 'node:os'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
import { execFileSync, spawnSync } from 'node:child_process'
|
|
7
|
+
|
|
8
|
+
const root = fileURLToPath(new URL('../', import.meta.url))
|
|
9
|
+
const scratch = await mkdtemp(join(tmpdir(), 'create-apptify-test-'))
|
|
10
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
11
|
+
const env = { ...process.env, npm_config_cache: join(scratch, 'cache'), npm_config_offline: 'true' }
|
|
12
|
+
const installer = join(scratch, 'installer')
|
|
13
|
+
const creator = join(installer, 'node_modules/create-apptify')
|
|
14
|
+
const library = join(installer, 'node_modules/apptify')
|
|
15
|
+
const cli = join(creator, 'bin/create-apptify.mjs')
|
|
16
|
+
|
|
17
|
+
async function unpack(cwd, destination) {
|
|
18
|
+
const packed = JSON.parse(execFileSync(npm, ['pack', '--ignore-scripts', '--json', '--pack-destination', scratch], { cwd, env, encoding: 'utf8' }))[0]
|
|
19
|
+
await mkdir(destination, { recursive: true })
|
|
20
|
+
execFileSync('tar', ['-xzf', join(scratch, packed.filename), '--strip-components=1', '-C', destination])
|
|
21
|
+
return packed
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// Use real tarballs in an installed layout, without fetching dependencies.
|
|
26
|
+
// The generator only reads/copies the library; it never imports its Vue code.
|
|
27
|
+
const packed = await unpack(join(root, 'packages/create-apptify'), creator)
|
|
28
|
+
const files = new Set(packed.files.map(file => file.path))
|
|
29
|
+
for (const path of ['package.json', 'bin/create-apptify.mjs', 'README.md', 'LICENSE']) assert(files.has(path), 'Missing creator file: ' + path)
|
|
30
|
+
await unpack(root, library)
|
|
31
|
+
await mkdir(join(installer, 'node_modules/.bin'))
|
|
32
|
+
await symlink('../create-apptify/bin/create-apptify.mjs', join(installer, 'node_modules/.bin/create-apptify'))
|
|
33
|
+
await writeFile(join(installer, 'package.json'), '{"private":true,"dependencies":{"create-apptify":"0.1.0"}}\n')
|
|
34
|
+
|
|
35
|
+
const run = args => spawnSync(process.execPath, [cli, ...args], { cwd: installer, env, encoding: 'utf8' })
|
|
36
|
+
const help = run(['--help'])
|
|
37
|
+
assert.equal(help.status, 0, help.stderr)
|
|
38
|
+
assert.match(help.stdout, /npm create apptify@latest/)
|
|
39
|
+
assert.equal(run([]).status, 1)
|
|
40
|
+
assert.equal(run(['--unknown']).status, 1)
|
|
41
|
+
assert.equal(run(['one', 'two']).status, 1)
|
|
42
|
+
|
|
43
|
+
const app = join(scratch, 'my app')
|
|
44
|
+
const result = spawnSync(npm, ['create', 'apptify', '--offline', '--', app], { cwd: installer, env, encoding: 'utf8', timeout: 60_000 })
|
|
45
|
+
assert.equal(result.status, 0, result.stdout + result.stderr)
|
|
46
|
+
const manifest = JSON.parse(await readFile(join(app, 'package.json'), 'utf8'))
|
|
47
|
+
assert.match(manifest.dependencies.apptify, /^file:\.\/vendor\/apptify-/)
|
|
48
|
+
assert.match(await readFile(join(app, '.gitignore'), 'utf8'), /node_modules/)
|
|
49
|
+
await readFile(join(app, 'playground/App.vue'))
|
|
50
|
+
const archive = join(app, manifest.dependencies.apptify.slice('file:./'.length))
|
|
51
|
+
const portableManifest = JSON.parse(execFileSync('tar', ['-xOf', archive, 'package/package.json'], { encoding: 'utf8' }))
|
|
52
|
+
assert.equal(portableManifest.name, 'apptify')
|
|
53
|
+
|
|
54
|
+
const before = await readFile(join(app, 'package.json'), 'utf8')
|
|
55
|
+
const refused = run([app])
|
|
56
|
+
assert.equal(refused.status, 1)
|
|
57
|
+
assert.match(refused.stderr, /Destination must be empty/)
|
|
58
|
+
assert.equal(await readFile(join(app, 'package.json'), 'utf8'), before)
|
|
59
|
+
assert.equal(run([join(library, 'unsafe')]).status, 1)
|
|
60
|
+
const alias = join(scratch, 'library-alias')
|
|
61
|
+
await symlink(library, alias, 'dir')
|
|
62
|
+
assert.equal(run([join(alias, 'unsafe')]).status, 1)
|
|
63
|
+
|
|
64
|
+
const empty = join(scratch, 'existing-empty')
|
|
65
|
+
await mkdir(empty)
|
|
66
|
+
const copied = run([empty])
|
|
67
|
+
assert.equal(copied.status, 0, copied.stderr)
|
|
68
|
+
await readFile(join(empty, 'playground/App.vue'))
|
|
69
|
+
await rm(installer, { recursive: true, force: true })
|
|
70
|
+
execFileSync('tar', ['-t', '-f', archive])
|
|
71
|
+
console.log('create-apptify: packed CLI, npm create, portable archive, help, argument validation and overwrite protection passed.')
|
|
72
|
+
await rm(scratch, { recursive: true, force: true })
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error('Acceptance workspace retained: ' + scratch)
|
|
75
|
+
throw error
|
|
76
|
+
}
|