fulldev-ui 0.6.0-beta.0 → 0.6.0-beta.2

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 (175) hide show
  1. package/astro.config.ts +10 -2
  2. package/example.svelte +0 -0
  3. package/package.json +12 -7
  4. package/parent.svelte +0 -0
  5. package/pnpm-lock.yaml +301 -35
  6. package/src/App.svelte +0 -0
  7. package/src/blocks/Products.astro +53 -72
  8. package/src/components/Card.astro +2 -2
  9. package/src/components/Cart.astro +12 -3
  10. package/src/components/CartAdd.svelte +76 -0
  11. package/src/components/CartCheckout.svelte +58 -0
  12. package/src/components/CartForm.astro +87 -88
  13. package/src/components/CartForm.svelte +130 -0
  14. package/src/components/CartList.astro +84 -79
  15. package/src/components/CartList.svelte +88 -0
  16. package/src/components/CartQuantity.svelte +81 -0
  17. package/src/components/CartSummary.astro +8 -94
  18. package/src/components/CartTotal.svelte +15 -0
  19. package/src/components/Dialog.astro +1 -0
  20. package/src/components/Drawer.astro +1 -0
  21. package/src/components/Gallery.astro +3 -1
  22. package/src/components/Header.astro +2 -0
  23. package/src/components/Image.astro +2 -2
  24. package/src/components/Input.astro +17 -9
  25. package/src/components/ProductCard.astro +52 -0
  26. package/src/components/Prose.astro +1 -1
  27. package/src/components/Search.astro +106 -43
  28. package/src/components/Section.astro +11 -269
  29. package/src/components/Select.astro +1 -0
  30. package/src/components/_CartList backup.astro +125 -0
  31. package/src/components/_CartList copy.astro +213 -0
  32. package/src/components/_CartListSimple.astro +148 -0
  33. package/src/content/categories/mugs.md +7 -0
  34. package/src/content/config.ts +24 -4
  35. package/src/content/{pages/docs → docs}/_internationalization.mdx +0 -1
  36. package/src/content/{pages/docs → docs}/_using-blocks.mdx +0 -1
  37. package/src/content/{pages/docs → docs}/_using-presets.mdx +0 -1
  38. package/src/content/{pages/docs → docs}/blocks.mdx +0 -1
  39. package/src/content/{pages/docs → docs}/collections/images.mdx +3 -2
  40. package/src/content/{pages/docs → docs}/collections/pages.mdx +0 -1
  41. package/src/content/{pages/docs → docs}/collections/presets.mdx +0 -1
  42. package/src/content/{pages/docs → docs}/collections.mdx +0 -1
  43. package/src/content/{pages/docs → docs}/components/_card.mdx +0 -2
  44. package/src/content/{pages/docs → docs}/components/_dialog.mdx +0 -2
  45. package/src/content/{pages/docs → docs}/components/_drawer.mdx +0 -2
  46. package/src/content/{pages/docs → docs}/components/_localeswitcher.mdx +0 -2
  47. package/src/content/{pages/docs → docs}/components/_switch.mdx +0 -2
  48. package/src/content/{pages/docs → docs}/components/_tagline.mdx +0 -2
  49. package/src/content/{pages/docs → docs}/components/_toggle.mdx +0 -2
  50. package/src/content/{pages/docs → docs}/components/avatar.mdx +0 -2
  51. package/src/content/{pages/docs → docs}/components/badge.mdx +0 -2
  52. package/src/content/{pages/docs → docs}/components/badges.mdx +0 -2
  53. package/src/content/{pages/docs → docs}/components/button.mdx +0 -2
  54. package/src/content/{pages/docs → docs}/components/buttons.mdx +0 -2
  55. package/src/content/{pages/docs → docs}/components/channel.mdx +0 -2
  56. package/src/content/{pages/docs → docs}/components/channels.mdx +0 -2
  57. package/src/content/{pages/docs → docs}/components/checkbox.mdx +0 -2
  58. package/src/content/{pages/docs → docs}/components/code.mdx +0 -2
  59. package/src/content/{pages/docs → docs}/components/heading.mdx +0 -2
  60. package/src/content/{pages/docs → docs}/components/icon.mdx +0 -2
  61. package/src/content/{pages/docs → docs}/components/image.mdx +0 -2
  62. package/src/content/{pages/docs → docs}/components/input.mdx +0 -2
  63. package/src/content/{pages/docs → docs}/components/label.mdx +0 -2
  64. package/src/content/{pages/docs → docs}/components/lead.mdx +0 -2
  65. package/src/content/{pages/docs → docs}/components/link.mdx +0 -2
  66. package/src/content/{pages/docs → docs}/components/links.mdx +0 -2
  67. package/src/content/{pages/docs → docs}/components/list.mdx +0 -2
  68. package/src/content/{pages/docs → docs}/components/logo.mdx +0 -2
  69. package/src/content/{pages/docs → docs}/components/menu.mdx +0 -2
  70. package/src/content/{pages/docs → docs}/components/paragraph.mdx +0 -2
  71. package/src/content/{pages/docs → docs}/components/prose.mdx +0 -2
  72. package/src/content/{pages/docs → docs}/components/rating.mdx +0 -2
  73. package/src/content/{pages/docs → docs}/components/section.mdx +0 -2
  74. package/src/content/{pages/docs → docs}/components/select.mdx +0 -2
  75. package/src/content/{pages/docs → docs}/components/social.mdx +0 -2
  76. package/src/content/{pages/docs → docs}/components/socials.mdx +0 -2
  77. package/src/content/{pages/docs → docs}/components/switch.mdx +0 -2
  78. package/src/content/{pages/docs → docs}/components/table.mdx +0 -2
  79. package/src/content/{pages/docs → docs}/components/tagline.mdx +0 -2
  80. package/src/content/{pages/docs → docs}/components/textarea.mdx +0 -2
  81. package/src/content/{pages/docs → docs}/components/themer.mdx +0 -2
  82. package/src/content/{pages/docs → docs}/components.mdx +0 -1
  83. package/src/content/{pages/docs → docs}/customization.mdx +0 -1
  84. package/src/content/{pages/docs → docs}/frameworks.mdx +0 -1
  85. package/src/content/{pages/docs → docs}/generating-pages.mdx +0 -1
  86. package/src/content/{pages/docs → docs}/index.mdx +0 -1
  87. package/src/content/{pages/docs → docs}/installation.mdx +0 -1
  88. package/src/content/{pages/docs → docs}/layouts.mdx +0 -1
  89. package/src/content/layouts/base.yml +101 -0
  90. package/src/content/layouts/docs.yml +70 -0
  91. package/src/content/pages/blocks/_categories.mdx +0 -2
  92. package/src/content/pages/blocks/_footer.mdx +0 -2
  93. package/src/content/pages/blocks/_header.mdx +0 -2
  94. package/src/content/pages/blocks/_jobs.mdx +0 -2
  95. package/src/content/pages/blocks/_prices.mdx +0 -2
  96. package/src/content/pages/blocks/_product.mdx +0 -2
  97. package/src/content/pages/blocks/_products.mdx +0 -2
  98. package/src/content/pages/blocks/_stats.mdx +0 -2
  99. package/src/content/pages/blocks/banner.mdx +0 -2
  100. package/src/content/pages/blocks/colleagues.mdx +0 -2
  101. package/src/content/pages/blocks/contact.mdx +0 -2
  102. package/src/content/pages/blocks/content.mdx +0 -2
  103. package/src/content/pages/blocks/cta.mdx +0 -2
  104. package/src/content/pages/blocks/features.mdx +0 -2
  105. package/src/content/pages/blocks/hero.mdx +0 -2
  106. package/src/content/pages/blocks/intro.mdx +0 -2
  107. package/src/content/pages/blocks/posts.mdx +0 -2
  108. package/src/content/pages/blocks/reviews.mdx +0 -2
  109. package/src/content/pages/index.mdx +0 -2
  110. package/src/content/pages/showcase/anti-slip-profiles.md +2 -2
  111. package/src/content/pages/showcase/fulldev-ui.md +1 -1
  112. package/src/content/pages/showcase/lavis-detailing.md +1 -1
  113. package/src/content/pages/showcase/leren-trainingsacteren.md +1 -1
  114. package/src/content/pages/showcase/miele-witgoedcenter-amsterdam.md +1 -1
  115. package/src/content/pages/showcase/sloepverhuur-bolsward.md +1 -1
  116. package/src/content/pages/showcase/stark-vulcanising-products.md +1 -1
  117. package/src/content/pages/showcase/the-gym-haren.md +1 -1
  118. package/src/content/pages/showcase/van-dillen-antieke-bouwmaterialen.md +1 -1
  119. package/src/content/pages/showcase.mdx +0 -1
  120. package/src/content/products/product.md +20 -0
  121. package/src/env.d.ts +1 -0
  122. package/src/integration/index.ts +20 -8
  123. package/src/layouts/CategoryLayout.astro +12 -17
  124. package/src/layouts/DocLayout.astro +17 -0
  125. package/src/layouts/Layout.astro +11 -40
  126. package/src/layouts/PageLayout.astro +6 -12
  127. package/src/layouts/PostLayout.astro +6 -12
  128. package/src/layouts/ProductLayout.astro +28 -33
  129. package/src/pages/[...category].astro +17 -0
  130. package/src/pages/[...doc].astro +17 -0
  131. package/src/pages/[...page].astro +6 -25
  132. package/src/pages/[...post].astro +17 -0
  133. package/src/pages/[...product].astro +17 -0
  134. package/src/pages/test.astro +1 -16
  135. package/src/schemas/archive/_pageSchema.ts +94 -0
  136. package/src/schemas/categorySchema.ts +16 -0
  137. package/src/schemas/components/banner.ts +3 -0
  138. package/src/schemas/components/card.ts +1 -1
  139. package/src/schemas/components/footer.ts +1 -0
  140. package/src/schemas/components/header.ts +1 -0
  141. package/src/schemas/components/link.ts +21 -14
  142. package/src/schemas/components/section.ts +2 -0
  143. package/src/schemas/components/sections.ts +1 -1
  144. package/src/schemas/components/sidebar.ts +1 -0
  145. package/src/schemas/components/subheader.ts +1 -0
  146. package/src/schemas/components/writeup.ts +1 -1
  147. package/src/schemas/docSchema.ts +10 -0
  148. package/src/schemas/fields/categories.ts +3 -0
  149. package/src/schemas/fields/description.ts +3 -0
  150. package/src/schemas/fields/href.ts +3 -0
  151. package/src/schemas/fields/image.ts +24 -0
  152. package/src/schemas/fields/images.ts +4 -0
  153. package/src/schemas/fields/order.ts +3 -0
  154. package/src/schemas/fields/price.ts +3 -0
  155. package/src/schemas/fields/products.ts +5 -0
  156. package/src/schemas/fields/seo.ts +12 -0
  157. package/src/schemas/fields/soldout.ts +3 -0
  158. package/src/schemas/{components/price.ts → fields/title.ts} +1 -1
  159. package/src/schemas/fields/variants.ts +3 -0
  160. package/src/schemas/layoutSchema.ts +28 -0
  161. package/src/schemas/pageSchema.ts +12 -86
  162. package/src/schemas/postSchema.ts +16 -0
  163. package/src/schemas/productSchema.ts +22 -0
  164. package/src/stores/cart.svelte.ts +79 -0
  165. package/src/stores/cart.ts +59 -6
  166. package/src/utils/formatEntries.ts +8 -0
  167. package/src/utils/formatEntry.ts +29 -0
  168. package/src/utils/getHref.ts +22 -0
  169. package/svelte.config.js +5 -0
  170. package/src/content/presets/base.yml +0 -100
  171. package/src/content/presets/docs.yml +0 -6
  172. package/src/schemas/components/images.ts +0 -4
  173. package/src/schemas/presetSchema.ts +0 -3
  174. package/src/schemas/utils/categories.ts +0 -3
  175. package/src/schemas/utils/navigation.ts +0 -8
@@ -1,59 +1,122 @@
1
1
  ---
2
- import Dialog from 'fulldev-ui/components/Dialog.astro'
2
+ import { getCollection } from 'astro:content'
3
+ import { getHref } from 'fulldev-ui/utils/getHref'
4
+ import Button from './Button.astro'
5
+ import Element from './Element.astro'
6
+ import Heading from './Heading.astro'
7
+ import Input from './Input.astro'
8
+ import Paragraph from './Paragraph.astro'
3
9
 
4
- const { variant = 'secondary', ...rest } = Astro.props
10
+ const pages = await getCollection('pages')
11
+ const products = await getCollection('products')
12
+ const categories = await getCollection('categories')
13
+ const posts = await getCollection('posts')
14
+ const docs = await getCollection('docs')
15
+ const entries = [...pages, ...categories, ...products, ...posts, ...docs]
5
16
  ---
6
17
 
7
- <Dialog
8
- class:list="search"
9
- id="search"
18
+ <script>
19
+ document.addEventListener('astro:page-load', () => {
20
+ const input = document.querySelector('.search-input')
21
+ const items = document.querySelectorAll('.search-item')
22
+
23
+ input?.addEventListener('input', (e) => {
24
+ if (!(e.target instanceof HTMLInputElement)) return
25
+ const value = e.target.value.toLowerCase()
26
+ items.forEach((item) => {
27
+ if (!(item instanceof HTMLElement)) return
28
+
29
+ const title =
30
+ item.querySelector('.heading')?.textContent?.toLowerCase() || ''
31
+ const description =
32
+ item.querySelector('.paragraph')?.textContent?.toLowerCase() || ''
33
+
34
+ const isVisible = title.includes(value) || description.includes(value)
35
+ item.classList.toggle('hide', !isVisible)
36
+ })
37
+ })
38
+ })
39
+ </script>
40
+
41
+ <Button
42
+ class:list="search-button"
43
+ variant="secondary"
44
+ size="sm"
10
45
  icon="search"
11
- {variant}
12
- {...rest}
46
+ onclick={`document.getElementById('search').showModal()`}
13
47
  />
14
48
 
15
- <style is:global >
16
- :root {
17
- --pagefind-ui-primary: var(--brand-11);
18
- --pagefind-ui-text: var(--base-12);
19
- --pagefind-ui-background: var(--base-2);
20
- --pagefind-ui-border: var(--base-6);
21
- --pagefind-ui-tag: var(--base-6);
22
- }
49
+ <dialog
50
+ class="search"
51
+ id="search"
52
+ onclick={`event.target === this && this.close()`}
53
+ >
54
+ <Element class:list="search-container">
55
+ <Element class:list="search-content">
56
+ <Input
57
+ class:list="search-input"
58
+ icon="search"
59
+ placeholder="Search"
60
+ />
61
+ <Element class:list="search-list">
62
+ {
63
+ entries.map(({ collection, slug, data }) => (
64
+ <Element
65
+ as="a"
66
+ href={getHref(collection, slug)}
67
+ class="search-item hide"
68
+ >
69
+ <Heading
70
+ text={data.title}
71
+ level={6}
72
+ />
73
+ <Paragraph
74
+ set:text={'description' in data ? data.description : undefined}
75
+ />
76
+ </Element>
77
+ ))
78
+ }
79
+ </Element>
80
+ </Element>
81
+ </Element>
82
+ </dialog>
23
83
 
24
- @media (max-width: 1023.999px) {
25
- .search,
26
- #search,
27
- #search-button {
28
- display: none !important;
29
- }
30
- }
84
+ <style is:global>
85
+ @layer fulldev {
86
+ .search {
87
+ @apply container h-full w-full max-w-screen-md rounded-lg !border-none bg-transparent py-24 outline-none backdrop:bg-black/50;
31
88
 
32
- .dialog div {
33
- width: 100%;
34
- }
89
+ &:is(.dark &) {
90
+ color-scheme: dark;
91
+ }
35
92
 
36
- .pagefind-ui__search-input {
37
- outline: none !important;
38
- border: 1px solid var(--base-7);
39
- color: var(--base-11);
93
+ .search-container {
94
+ @apply w-full overflow-hidden rounded-lg border bg-background shadow-md;
95
+ }
40
96
 
41
- &::placeholder {
42
- color: var(--base-11);
43
- }
97
+ .search-content {
98
+ @apply max-h-[400px] w-full overflow-y-auto;
99
+ }
44
100
 
45
- &:hover {
46
- outline: none;
47
- }
101
+ .input {
102
+ @apply m-5;
103
+ }
48
104
 
49
- &:focus {
50
- outline: none;
51
- box-shadow: inset 0 0 0 2px var(--base-8);
52
- border-color: var(--base-8);
53
- }
54
- }
105
+ .search-list {
106
+ @apply flex h-full w-full shrink grow-0 flex-col;
107
+ }
108
+
109
+ .search-item {
110
+ @apply border-t p-5 transition-colors hover:bg-accent;
55
111
 
56
- .pagefind-ui__search-clear {
57
- background: transparent !important;
112
+ &.hide {
113
+ @apply hidden;
114
+ }
115
+ }
116
+
117
+ .paragraph {
118
+ @apply mt-2 truncate text-sm text-muted-foreground;
119
+ }
120
+ }
58
121
  }
59
122
  </style>
@@ -1,86 +1,15 @@
1
1
  ---
2
- import type { ComponentProps, HTMLAttributes, HTMLTag } from 'astro/types'
3
- import Button from 'fulldev-ui/components/Button.astro'
4
- import Buttons from 'fulldev-ui/components/Buttons.astro'
5
- import type Card from 'fulldev-ui/components/Card.astro'
6
- import Cards from 'fulldev-ui/components/Cards.astro'
7
- import Element from 'fulldev-ui/components/Element.astro'
8
- import Heading from 'fulldev-ui/components/Heading.astro'
9
- import Image from 'fulldev-ui/components/Image.astro'
10
- import Badge from './Badge.astro'
11
- import Lead from './Lead.astro'
12
- import List from './List.astro'
13
- import Paragraph from './Paragraph.astro'
14
- import Price from './Price.astro'
15
- import Rating from './Rating.astro'
16
- import Tagline from './Tagline.astro'
2
+ import { getEntries } from 'astro:content'
17
3
 
18
- interface Props extends HTMLAttributes<'section'> {
19
- as?: HTMLTag
20
- size?: 'sm' | 'md' | 'lg' | undefined
21
- image?: ComponentProps<typeof Image>
22
- buttons?: ComponentProps<typeof Buttons>['buttons']
23
- button?: ComponentProps<typeof Button> | undefined
24
- variant?: ComponentProps<typeof Button>['variant']
25
- cards?: ComponentProps<typeof Cards>['cards']
26
- panel?: ComponentProps<typeof Card>['panel']
4
+ interface Props {
27
5
  component?: string
28
- heading?: any
29
- background?: any
30
- lead?: any
31
- rating?: any
32
- tagline?: any
33
- badge?: any
34
- level?: any
35
- paragraph?: any
36
- dark?: boolean
37
- list?: any
38
- price?: any
39
- center?: boolean
40
- inset?: boolean
41
- reverse?: boolean
42
- frame?: 'fill' | 'panel' | 'viewport' | undefined
43
- position?: 'contain' | 'inset' | 'background' | undefined
44
- structure?:
45
- | 'left'
46
- | 'center'
47
- | 'spread'
48
- | 'split'
49
- | 'grid'
50
- | 'masonry'
51
- | 'carousel'
52
- | 'stack'
53
- | undefined
6
+ [key: string]: any
54
7
  }
55
8
 
56
- const { component, ...props } = Astro.props
9
+ let { component, products, categories, ...rest } = Astro.props
57
10
 
58
- const {
59
- as = 'section',
60
- size = 'md',
61
- variant = 'secondary',
62
- structure = 'left',
63
- inset = false,
64
- panel = false,
65
- reverse = false,
66
- dark = false,
67
- frame = 'viewport',
68
- position = 'background',
69
- level = 2,
70
- rating,
71
- tagline,
72
- badge,
73
- heading,
74
- lead,
75
- paragraph,
76
- list,
77
- price,
78
- buttons,
79
- image,
80
- background,
81
- cards,
82
- ...rest
83
- } = props
11
+ products = products && (await getEntries(products))
12
+ categories = categories && (await getEntries(categories))
84
13
 
85
14
  const allComponents = {
86
15
  ...import.meta.glob('/src/**/*.astro'),
@@ -93,201 +22,14 @@ const componentPath = Object.keys(allComponents).find(
93
22
 
94
23
  const Component =
95
24
  componentPath && (await (allComponents[componentPath] as any)()).default
96
-
97
- const hasCards = cards && cards.length > 0
98
25
  ---
99
26
 
100
27
  {
101
- Component ? (
102
- <Component {...props} />
103
- ) : (
104
- <Element
105
- class:list="section"
106
- panel={hasCards ? undefined : panel}
107
- {as}
108
- {size}
109
- {structure}
110
- {inset}
111
- {reverse}
112
- {dark}
113
- {position}
114
- {frame}
28
+ Component && (
29
+ <Component
30
+ {products}
31
+ {categories}
115
32
  {...rest}
116
- >
117
- <Element class:list="section-container">
118
- <Element class:list="section-segment">
119
- <Element class:list="section-content">
120
- <Rating
121
- {size}
122
- {...rating}
123
- />
124
- <Tagline
125
- text={tagline}
126
- {size}
127
- />
128
- <Badge
129
- {size}
130
- {...badge}
131
- />
132
- <Heading
133
- text={heading}
134
- {size}
135
- {level}
136
- />
137
- <Lead
138
- text={lead}
139
- {size}
140
- />
141
- <Paragraph
142
- text={paragraph}
143
- {size}
144
- />
145
- <List
146
- items={list}
147
- {size}
148
- />
149
- <Price
150
- value={price}
151
- {size}
152
- />
153
- <slot name="content" />
154
- </Element>
155
- <Buttons
156
- {size}
157
- {variant}
158
- {buttons}
159
- />
160
- <slot name="segment" />
161
- </Element>
162
- <Image {...image} />
163
- <Cards
164
- {size}
165
- {level}
166
- {cards}
167
- />
168
- <slot />
169
- </Element>
170
- </Element>
33
+ />
171
34
  )
172
35
  }
173
-
174
- <style is:global>
175
- @layer fulldev {
176
- .section {
177
- @apply relative flex w-full items-center pb-28 pt-14 first:pt-0;
178
-
179
- .section-container {
180
- @apply container z-10 w-full;
181
- }
182
-
183
- .section-segment {
184
- @apply z-10 gap-8 py-16;
185
- }
186
-
187
- .section-content {
188
- @apply max-w-screen-md gap-6;
189
- }
190
-
191
- &.frame-fill {
192
- @apply pb-28 pt-14 first:pt-0;
193
- }
194
-
195
- &.frame-viewport {
196
- @apply min-h-screen pb-28 pt-14;
197
-
198
- .section-container {
199
- @apply justify-center;
200
- }
201
- }
202
-
203
- &.frame-panel {
204
- @apply px-gutter first:pt-gutter;
205
-
206
- .section-container {
207
- @apply relative overflow-hidden rounded-lg border bg-card;
208
- }
209
- }
210
-
211
- &.position-contain {
212
- .image {
213
- @apply h-auto w-full object-contain;
214
- }
215
- }
216
-
217
- &.position-background {
218
- .image {
219
- @apply absolute inset-0 h-full max-h-none w-full max-w-none object-cover opacity-30;
220
- }
221
- }
222
-
223
- &.position-inset {
224
- .section-container {
225
- @apply px-0;
226
- }
227
-
228
- .section-segment {
229
- @apply px-gutter;
230
- }
231
-
232
- .image {
233
- @apply h-auto w-full object-cover;
234
- }
235
- }
236
-
237
- &.dark {
238
- @apply bg-background;
239
- }
240
-
241
- &.structure-left {
242
- .section-container,
243
- .section-segment,
244
- .section-content {
245
- @apply flex flex-col items-start;
246
- }
247
- }
248
-
249
- &.structure-center {
250
- .section-container,
251
- .section-segment,
252
- .section-content {
253
- @apply flex flex-col items-center text-center;
254
- }
255
- }
256
-
257
- &.structure-split {
258
- .section-container {
259
- @apply grid auto-cols-fr gap-x-14 lg:grid-flow-col lg:items-center;
260
- }
261
-
262
- .section-segment,
263
- .section-content {
264
- @apply flex flex-col items-start;
265
- }
266
- }
267
-
268
- &.structure-spread {
269
- .section-container {
270
- @apply flex flex-col;
271
- }
272
-
273
- .section-segment {
274
- @apply flex w-full flex-row flex-wrap items-end justify-between;
275
- }
276
- }
277
-
278
- &.reverse {
279
- &:not(.structure-split) {
280
- .section-segment {
281
- @apply order-last;
282
- }
283
- }
284
-
285
- @media (min-width: 1024px) {
286
- .section-segment {
287
- @apply order-last;
288
- }
289
- }
290
- }
291
- }
292
- }
293
- </style>
@@ -25,6 +25,7 @@ const {
25
25
  ---
26
26
 
27
27
  <Element
28
+ if={options}
28
29
  class:list="select"
29
30
  as="label"
30
31
  for={id}
@@ -0,0 +1,125 @@
1
+ <!-- ---
2
+ import Element from 'fulldev-ui/components/Element.astro'
3
+ import Image from 'fulldev-ui/components/Image.astro'
4
+ import Button from './Button.astro'
5
+ import Heading from './Heading.astro'
6
+ import Input from './Input.astro'
7
+ import Price from './Price.astro'
8
+
9
+ const { ...rest } = Astro.props
10
+ ---
11
+
12
+ <Element
13
+ if={true}
14
+ class:list="cart-list"
15
+ {...rest}
16
+ />
17
+
18
+ <template id="cart-list-template">
19
+ <Element class="cart-list-card">
20
+ <Image src="/placeholder-portrait.webp" />
21
+ <Element class="cart-list-card-segment">
22
+ <Element class="cart-list-card-content">
23
+ <Heading
24
+ level={6}
25
+ text="Product title"
26
+ />
27
+ <Price value={999} />
28
+ </Element>
29
+ <Element class="cart-list-card-actions">
30
+ <Input
31
+ type="number"
32
+ name="quantity"
33
+ value={1}
34
+ min={0}
35
+ />
36
+ <Button
37
+ variant="outline"
38
+ icon="trash"
39
+ type="button"
40
+ />
41
+ </Element>
42
+ </Element>
43
+ </Element>
44
+ </template>
45
+
46
+ <script>
47
+ import { $cart } from 'fulldev-ui/stores/cart.ts'
48
+ import { formatPrice } from 'fulldev-ui/utils/cart'
49
+
50
+ function setCards(items: any) {
51
+ const template = document.querySelector('template')
52
+ const container = document.querySelector('.cart-list')
53
+ if (!(container instanceof HTMLElement)) return
54
+ if (!(template instanceof HTMLTemplateElement)) return
55
+
56
+ container.innerHTML = ''
57
+
58
+ items.forEach((item: any, index: number) => {
59
+ const clone = template?.content.cloneNode(true)
60
+ if (!(clone instanceof DocumentFragment)) return
61
+ const card = clone.querySelector('.cart-list-card')
62
+ if (!card) return
63
+
64
+ const image = card.querySelector('img')
65
+ const heading = card.querySelector('.heading')
66
+ const price = card.querySelector('.price')
67
+ // const input = card.querySelector('.input-input')
68
+ const remove = card.querySelector('.button')
69
+
70
+ if (image) image.src = item.image
71
+ if (heading) heading.textContent = item.name
72
+ if (price) price.textContent = formatPrice(item.price)
73
+
74
+ remove?.addEventListener('click', () => {
75
+ const currentCart = $cart.get()
76
+ const newCart = [...currentCart]
77
+ newCart.splice(index, 1)
78
+ $cart.set(newCart)
79
+ })
80
+
81
+ container.appendChild(clone)
82
+ })
83
+ }
84
+
85
+ document.addEventListener('astro:page-load', () => {
86
+ setCards($cart.get())
87
+
88
+ $cart.subscribe((items: any) => {
89
+ setCards(items)
90
+ })
91
+ })
92
+ </script>
93
+
94
+ <style is:global>
95
+ @layer fulldev {
96
+ .cart-list {
97
+ @apply flex flex-col text-foreground;
98
+
99
+ .cart-list-card {
100
+ @apply flex w-full gap-5;
101
+
102
+ &:not(:first-child) {
103
+ @apply mt-5 border-t pt-5;
104
+ }
105
+ }
106
+
107
+ .image {
108
+ @apply block h-auto w-24;
109
+ }
110
+
111
+ .cart-list-card-segment {
112
+ @apply flex h-full w-full flex-col justify-between gap-4;
113
+ }
114
+
115
+ .cart-list-card-content,
116
+ .cart-list-card-actions {
117
+ @apply flex justify-between gap-2;
118
+ }
119
+
120
+ .input {
121
+ @apply w-16;
122
+ }
123
+ }
124
+ }
125
+ </style> -->