fulldev-ui 0.5.0-beta.5 → 0.5.0-beta.7

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 (42) hide show
  1. package/CONTRIBUTING.md +10 -4
  2. package/astro.config.ts +2 -3
  3. package/package.json +4 -2
  4. package/pnpm-lock.yaml +31 -69
  5. package/src/blocks/Article.astro +31 -12
  6. package/src/blocks/Banner.astro +2 -1
  7. package/src/blocks/Product.astro +11 -21
  8. package/src/components/Card.astro +1 -1
  9. package/src/components/Cart.astro +38 -0
  10. package/src/components/CartForm.astro +121 -0
  11. package/src/components/CartList.astro +134 -0
  12. package/src/components/CartSummary.astro +146 -0
  13. package/src/components/Drawer.astro +41 -8
  14. package/src/components/Footer.astro +0 -1
  15. package/src/components/Form.astro +49 -0
  16. package/src/components/Header.astro +5 -8
  17. package/src/components/Image.astro +0 -1
  18. package/src/components/Input.astro +6 -0
  19. package/src/components/Price.astro +7 -11
  20. package/src/components/Search.astro +1 -4
  21. package/src/components/Section.astro +0 -1
  22. package/src/components/Sidebar.astro +1 -1
  23. package/src/components/Toc.astro +3 -6
  24. package/src/components/docs/PropsTable.astro +1 -1
  25. package/src/components/experimental/Form.astro +29 -5
  26. package/src/content/config.ts +2 -1
  27. package/src/content/pages/base/select.mdx +0 -8
  28. package/src/content/pages/base/textarea.mdx +0 -5
  29. package/src/content/presets/base.yml +1 -2
  30. package/src/content/presets/docs.yml +4 -4
  31. package/src/env.d.ts +1 -1
  32. package/src/layouts/DocsLayout.astro +23 -35
  33. package/src/layouts/Layout.astro +12 -16
  34. package/src/layouts/OverviewLayout.astro +5 -2
  35. package/src/layouts/PostLayout.astro +7 -10
  36. package/src/schemas/pageSchema.ts +53 -28
  37. package/src/schemas/presetSchema.ts +3 -0
  38. package/src/schemas/utils/navigation.ts +5 -1
  39. package/src/stores/cart.ts +23 -0
  40. package/src/utils/cart.ts +36 -0
  41. package/tsconfig.json +1 -3
  42. /package/src/types/{global-props.d.ts → global-props.ts} +0 -0
@@ -2,6 +2,7 @@ import { defineCollection } from 'astro:content'
2
2
  import imageLoader from 'fulldev-ui/loaders/imageLoader.ts'
3
3
  import imageSchema from 'fulldev-ui/schemas/imageSchema.ts'
4
4
  import pageSchema from 'fulldev-ui/schemas/pageSchema.ts'
5
+ import presetSchema from 'fulldev-ui/schemas/presetSchema.ts'
5
6
 
6
7
  export const collections = {
7
8
  pages: defineCollection({
@@ -10,7 +11,7 @@ export const collections = {
10
11
  }),
11
12
  presets: defineCollection({
12
13
  type: 'data',
13
- schema: pageSchema,
14
+ schema: presetSchema,
14
15
  }),
15
16
  images: defineCollection({
16
17
  loader: imageLoader,
@@ -2,14 +2,6 @@
2
2
  presets: [docs]
3
3
 
4
4
  title: Select
5
-
6
- example:
7
- label: Select
8
- name: select
9
- placeholder: Select an option
10
- options:
11
- - Option 1
12
- - Option 2
13
5
  ---
14
6
 
15
7
  # Select
@@ -2,11 +2,6 @@
2
2
  presets: [docs]
3
3
 
4
4
  title: Textarea
5
-
6
- example:
7
- name: textarea
8
- placeholder: Write a message..
9
- label: Textarea
10
5
  ---
11
6
 
12
7
  # Textarea
@@ -10,9 +10,8 @@ code:
10
10
  posthog.init('phc_mVacbe8Xydu0UZlh4bNw5EGisvzyRcpqXEEuEEp5lOY',{api_host:'https://eu.i.posthog.com', person_profiles: 'identified_only' // or 'always' to create profiles for anonymous users as well
11
11
  })
12
12
  </script>
13
- header: true
14
13
  navigation:
15
- cart: Winkelwagen
14
+ header: true
16
15
  company: Fulldev UI
17
16
  buttons:
18
17
  - text: Docs
@@ -1,6 +1,6 @@
1
1
  component: DocsLayout
2
- presets: [base]
3
2
 
4
- sidebar: true
5
- header: false
6
- toc: 'On this page'
3
+ navigation:
4
+ sidebar: true
5
+ header: false
6
+ toc: 'On this page'
package/src/env.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /// <reference types="astro/client" />
2
- /// <reference path="../.astro/types.d.ts" />
2
+ /// <reference path="../.astro/types.d.ts" />
@@ -2,14 +2,13 @@
2
2
  import type { ComponentProps } from 'astro/types'
3
3
  import Button from 'fulldev-ui/components/Button.astro'
4
4
  import Element from 'fulldev-ui/components/Element.astro'
5
- import Prose from 'fulldev-ui/components/experimental/Prose.astro'
6
5
  import Layout from 'fulldev-ui/layouts/Layout.astro'
7
6
  import { crush } from 'radash'
7
+ import PostLayout from './PostLayout.astro'
8
8
 
9
9
  type Props = ComponentProps<typeof Layout>
10
10
 
11
- const { render, slug, navigation, ...rest } = Astro.props
12
- const { Content } = await render()
11
+ const { slug, navigation } = Astro.props
13
12
 
14
13
  const flatButtons = crush((navigation as any)?.buttons ?? {})
15
14
  const slugs = Object.entries(flatButtons)
@@ -21,45 +20,34 @@ const prevSlug = slugs[slugIndex - 1]
21
20
  const nextSlug = slugs[slugIndex + 1]
22
21
  ---
23
22
 
24
- <Layout
23
+ <PostLayout
25
24
  class:list="docs-layout"
26
- {render}
27
- {slug}
28
- {navigation}
29
- {...rest}
25
+ {...Astro.props}
30
26
  >
31
- <Prose>
32
- {Content && <Content />}
33
- <Element class:list={['prev-next', { 'next-only': !prevSlug }]}>
34
- <Button
35
- if={prevSlug}
36
- slug={prevSlug}
37
- icon="arrow-left"
38
- variant="secondary"
39
- />
40
- <Button
41
- if={nextSlug}
42
- slug={nextSlug}
43
- icon="arrow-right"
44
- variant="secondary"
45
- reverse={true}
46
- />
47
- </Element>
48
- </Prose>
49
- </Layout>
27
+ <Element
28
+ class:list={['prev-next', { 'next-only': !prevSlug }]}
29
+ slot="prose"
30
+ >
31
+ <Button
32
+ if={prevSlug}
33
+ slug={prevSlug}
34
+ icon="arrow-left"
35
+ variant="secondary"
36
+ />
37
+ <Button
38
+ if={nextSlug}
39
+ slug={nextSlug}
40
+ icon="arrow-right"
41
+ variant="secondary"
42
+ reverse={true}
43
+ />
44
+ </Element>
45
+ </PostLayout>
50
46
 
51
47
  <style lang="scss" is:global>
52
48
  @layer fulldev {
53
49
  .docs-layout {
54
50
  .prose {
55
- --screen: 768px;
56
- padding: var(--space-6) var(--gutter);
57
- color: var(--color-12);
58
-
59
- > h1 + p {
60
- color: var(--color-11);
61
- }
62
-
63
51
  > a,
64
52
  > p > a {
65
53
  color: var(--brand-11);
@@ -7,9 +7,9 @@ import Footer from 'fulldev-ui/blocks/Footer.astro'
7
7
  import Element from 'fulldev-ui/components/Element.astro'
8
8
  import Head from 'fulldev-ui/components/Head.astro'
9
9
  import Header from 'fulldev-ui/components/Header.astro'
10
+ import Section from 'fulldev-ui/components/Section.astro'
10
11
  import Sections from 'fulldev-ui/components/sections.astro'
11
12
  import Sidebar from 'fulldev-ui/components/Sidebar.astro'
12
- import Toc from 'fulldev-ui/components/Toc.astro'
13
13
  import type { GlobalProps } from 'fulldev-ui/types/global-props'
14
14
 
15
15
  type Props = GlobalProps &
@@ -19,6 +19,7 @@ type Props = GlobalProps &
19
19
  header?: ComponentProps<typeof Header>
20
20
  footer?: ComponentProps<typeof Footer>
21
21
  sections?: ComponentProps<typeof Sections>['sections']
22
+ section?: ComponentProps<typeof Section> | undefined
22
23
  banner?: any
23
24
  toc?: any
24
25
  sidebar?: any
@@ -47,6 +48,7 @@ const {
47
48
  toc,
48
49
  sections,
49
50
  theme,
51
+ section,
50
52
  banner,
51
53
  code,
52
54
  themeselect,
@@ -66,34 +68,30 @@ const {
66
68
  </slot>
67
69
  <slot name="header">
68
70
  <Header
69
- class:list={{
70
- 'for-sidebar': sidebar,
71
- }}
72
- if={navigation || header}
73
- {...navigation}
71
+ {...navigation?.header === true ? navigation : {}}
74
72
  {...header}
75
73
  />
76
74
  </slot>
77
75
  <div class="core">
78
76
  <slot name="sidebar">
79
77
  <Sidebar
80
- if={sidebar}
81
- {...navigation}
78
+ {...navigation?.sidebar === true ? navigation : {}}
79
+ logo={navigation?.sidebar?.header
80
+ ? undefined
81
+ : navigation?.sidebar?.logo}
82
+ company={navigation?.sidebar?.header
83
+ ? undefined
84
+ : navigation?.sidebar?.company}
82
85
  {...sidebar}
83
86
  />
84
87
  </slot>
85
88
  <main data-pagefind-body>
86
89
  <slot>
90
+ <Section {...section} />
87
91
  <Article />
88
92
  <Sections {sections} />
89
93
  </slot>
90
94
  </main>
91
- <slot name="toc">
92
- <Toc
93
- heading={toc}
94
- {render}
95
- />
96
- </slot>
97
95
  </div>
98
96
  <slot name="footer">
99
97
  <Footer {...footer} />
@@ -112,7 +110,6 @@ const {
112
110
  }
113
111
 
114
112
  body {
115
- --screen: 100vw;
116
113
  display: flex;
117
114
  flex-direction: column;
118
115
  background-color: var(--base-background);
@@ -144,7 +141,6 @@ const {
144
141
  background-color: var(--color-background);
145
142
  width: 100%;
146
143
  max-width: 100vw;
147
- overflow-x: hidden;
148
144
  }
149
145
  }
150
146
  }
@@ -11,7 +11,7 @@ import { getReferenceChildren } from 'fulldev-ui/utils/getReferenceChildren'
11
11
 
12
12
  type Props = ComponentProps<typeof Layout>
13
13
 
14
- const { slug, sections, title, description } = Astro.props
14
+ const { slug, sections, title, description, render } = Astro.props
15
15
 
16
16
  const folderChildren = await getFolderChildren(slug)
17
17
  const referenceChildren = await getReferenceChildren(slug)
@@ -33,7 +33,10 @@ const referenceChildren = await getReferenceChildren(slug)
33
33
  cards={referenceChildren}
34
34
  structure="grid"
35
35
  />
36
- <Article style={{ '--screen': '768px' }} />
36
+ <Article
37
+ {render}
38
+ toc={false}
39
+ />
37
40
  <Sections {sections} />
38
41
  <slot />
39
42
  </Layout>
@@ -3,22 +3,19 @@ import type { ComponentProps } from 'astro/types'
3
3
  import Article from 'fulldev-ui/blocks/Article.astro'
4
4
  import Sections from 'fulldev-ui/components/sections.astro'
5
5
  import Layout from 'fulldev-ui/layouts/Layout.astro'
6
- import Excerpt from '../blocks/Excerpt.astro'
7
6
 
8
7
  type Props = ComponentProps<typeof Layout>
9
8
 
10
- const { sections, title, description, ...rest } = Astro.props
9
+ const { sections, render, toc } = Astro.props
11
10
  ---
12
11
 
13
12
  <Layout {...Astro.props}>
14
- <Excerpt
15
- heading={title}
16
- align="start"
17
- text={description}
18
- style={{ '--screen': '768px' }}
19
- {...rest}
20
- />
21
- <Article />
13
+ <Article
14
+ {render}
15
+ {toc}
16
+ >
17
+ <slot name="prose" />
18
+ </Article>
22
19
  <Sections {sections} />
23
20
  <slot />
24
21
  </Layout>
@@ -4,6 +4,9 @@ import fulldevConfig from 'virtual:fulldev-ui/config'
4
4
  import footer from './components/footer'
5
5
  import header from './components/header'
6
6
  import image from './components/image'
7
+ import images from './components/images'
8
+ import price from './components/price'
9
+ import section from './components/section'
7
10
  import sections from './components/sections'
8
11
  import sidebar from './components/sidebar'
9
12
  import toc from './components/toc'
@@ -12,7 +15,7 @@ import navigation from './utils/navigation'
12
15
  import parents from './utils/parents'
13
16
  import pathSchema from './utils/pathSchema'
14
17
 
15
- const i18n = z
18
+ export const i18n = z
16
19
  .object({
17
20
  i18n: pathSchema('pages').optional(),
18
21
  })
@@ -24,7 +27,7 @@ const i18n = z
24
27
  return merged as typeof rest
25
28
  })
26
29
 
27
- const presets = z
30
+ export const presets = z
28
31
  .object({
29
32
  presets: z.array(pathSchema('presets')).optional(),
30
33
  })
@@ -48,29 +51,51 @@ const presets = z
48
51
  return mergedData as typeof rest
49
52
  })
50
53
 
51
- export default i18n.pipe(presets).pipe(
52
- z
53
- .object({
54
- component,
55
- parents,
56
- theme: z.enum(['light', 'dark']),
57
- lang: z.string(),
58
- seo: z
59
- .object({
60
- title: z.string().optional(),
61
- description: z.string().optional(),
62
- })
63
- .optional(),
64
- title: z.string(),
65
- description: z.string().optional(),
66
- image,
67
- sections,
68
- footer,
69
- header: z.boolean().or(header),
70
- sidebar: z.boolean().or(sidebar),
71
- navigation,
72
- toc,
73
- })
74
- .partial()
75
- .passthrough()
76
- )
54
+ export const basePreset = z
55
+ .object({})
56
+ .passthrough()
57
+ .transform(async (data) => {
58
+ if (!fulldevConfig.basePreset) return data
59
+ const baseEntry = await getEntry('presets', fulldevConfig.basePreset)
60
+ const mergedData = assign(baseEntry?.data ?? {}, data)
61
+ return mergedData as typeof data
62
+ })
63
+
64
+ export const page = z
65
+ .object({
66
+ component,
67
+ parents,
68
+ theme: z.enum(['light', 'dark']),
69
+ lang: z.string(),
70
+ seo: z
71
+ .object({
72
+ title: z.string().optional(),
73
+ description: z.string().optional(),
74
+ })
75
+ .optional(),
76
+ title: z.string(),
77
+ description: z.string().optional(),
78
+ image,
79
+ images,
80
+ section,
81
+ sections,
82
+ footer,
83
+ header: header,
84
+ sidebar: sidebar,
85
+ navigation,
86
+ toc,
87
+ price,
88
+ code: z.any(),
89
+ sizes: z.any(),
90
+ banner: z.any(),
91
+ _schema: z.any(),
92
+ uitverkocht: z.any(),
93
+ rating: z.any(),
94
+ variants: z.any(),
95
+ heading: z.any(),
96
+ href: z.any(),
97
+ })
98
+ .partial()
99
+ .strict()
100
+
101
+ export default i18n.pipe(basePreset).pipe(presets).pipe(page)
@@ -0,0 +1,3 @@
1
+ import { page } from './pageSchema'
2
+
3
+ export default page
@@ -1,4 +1,8 @@
1
+ import { z } from 'astro:content'
1
2
  import header from '../components/header'
2
3
  import sidebar from '../components/sidebar'
3
4
 
4
- export default sidebar.merge(header)
5
+ export default sidebar.merge(header).extend({
6
+ header: z.boolean().optional(),
7
+ sidebar: z.boolean().optional(),
8
+ })
@@ -0,0 +1,23 @@
1
+ import { persistentAtom } from '@nanostores/persistent'
2
+ import { computed } from 'nanostores'
3
+
4
+ // type Item = CollectionEntry<'products'>['data'] & {
5
+ // quantity: number
6
+ // }
7
+
8
+ type Item = any
9
+
10
+ export const $cart = persistentAtom<Item[] | []>('cart', [], {
11
+ encode: JSON.stringify,
12
+ decode: JSON.parse,
13
+ })
14
+
15
+ // export const cartIsOpen = atom(false)
16
+
17
+ export const $totalPrice = computed($cart, ($cart) =>
18
+ $cart.reduce((a, b) => +a + b.price * b.quantity, 0)
19
+ )
20
+
21
+ // export const totalQuantity = computed(cart, ($cart) =>
22
+ // $cart.reduce((a, b) => +a + b.quantity, 0)
23
+ // )
@@ -0,0 +1,36 @@
1
+ // import Stripe from 'stripe'
2
+
3
+ // const stripe = new Stripe(import.meta.env.STRIPE_SECRET_KEY)
4
+
5
+ const slugify = (input: string): string => {
6
+ return input
7
+ .toLowerCase()
8
+ .replace(/[^a-z0-9]+/g, '-')
9
+ .replace(/^-+|-+$/g, '')
10
+ }
11
+
12
+ export const generateProductId = (
13
+ slug: string,
14
+ variants?: string[] | undefined
15
+ ): string => {
16
+ const slugified = slugify(slug)
17
+
18
+ if (variants && variants.length > 0)
19
+ return `${slugified}--${variants.map((variant) => slugify(variant)).join('--')}`
20
+
21
+ return slugified
22
+ }
23
+
24
+ export const generateProductName = (
25
+ title: string,
26
+ variants?: string[] | undefined
27
+ ): string => {
28
+ if (variants && variants.length > 0)
29
+ return `${title} / ${variants.join(' / ')}`
30
+
31
+ return title
32
+ }
33
+
34
+ export const formatPrice = (price: number): string => {
35
+ return `€${price?.toFixed(2).replace('.', ',')}`
36
+ }
package/tsconfig.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "extends": "astro/tsconfigs/strictest",
3
+ "include": ["src", "astro.config.ts"],
3
4
  "compilerOptions": {
4
5
  "baseUrl": ".",
5
6
  "paths": {
@@ -8,7 +9,4 @@
8
9
  ]
9
10
  }
10
11
  },
11
- "exclude": [
12
- "dist"
13
- ]
14
12
  }