fulldev-ui 0.5.0-beta.4 → 0.5.0-beta.6

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 (60) hide show
  1. package/CONTRIBUTING.md +10 -4
  2. package/astro.config.ts +0 -2
  3. package/package.json +4 -2
  4. package/pnpm-lock.yaml +31 -69
  5. package/src/blocks/Banner.astro +2 -1
  6. package/src/blocks/Excerpt.astro +14 -0
  7. package/src/blocks/Product.astro +51 -22
  8. package/src/components/Card.astro +1 -1
  9. package/src/components/Cart.astro +36 -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 +119 -52
  14. package/src/components/Footer.astro +4 -0
  15. package/src/components/Form.astro +49 -0
  16. package/src/components/Header.astro +14 -12
  17. package/src/components/Input.astro +6 -0
  18. package/src/components/Menu.astro +56 -0
  19. package/src/components/Price.astro +7 -11
  20. package/src/components/Search.astro +1 -4
  21. package/src/components/Section.astro +2 -0
  22. package/src/components/Sidebar.astro +61 -111
  23. package/src/components/ThemeSelect.astro +3 -0
  24. package/src/components/Toc.astro +36 -94
  25. package/src/components/experimental/Form.astro +29 -5
  26. package/src/components/experimental/Gallery.astro +50 -126
  27. package/src/components/experimental/Prose.astro +32 -0
  28. package/src/content/pages/base/select.mdx +0 -8
  29. package/src/content/pages/base/textarea.mdx +0 -5
  30. package/src/content/pages/blocks/_product.mdx +73 -2
  31. package/src/content/pages/index.mdx +0 -2
  32. package/src/content/pages/layouts/_layout.mdx +8 -15
  33. package/src/content/pages/layouts/docslayout.mdx +10 -1
  34. package/src/content/pages/overview/components.mdx +5 -0
  35. package/src/content/pages/overview/content-collections.mdx +139 -0
  36. package/src/content/pages/overview/installation.mdx +25 -26
  37. package/src/content/pages/overview/introduction.mdx +16 -10
  38. package/src/content/pages/overview/theming.mdx +69 -0
  39. package/src/content/pages/schemas/page.mdx +6 -0
  40. package/src/content/presets/base.yml +57 -43
  41. package/src/content/presets/blocks.yml +0 -3
  42. package/src/content/presets/docs.yml +1 -61
  43. package/src/env.d.ts +1 -1
  44. package/src/layouts/Layout.astro +28 -14
  45. package/src/layouts/PostLayout.astro +24 -0
  46. package/src/layouts/ProductLayout.astro +5 -2
  47. package/src/schemas/components/header.ts +7 -9
  48. package/src/schemas/components/menu.ts +13 -0
  49. package/src/schemas/components/sidebar.ts +15 -0
  50. package/src/schemas/components/toc.ts +3 -0
  51. package/src/schemas/pageSchema.ts +54 -30
  52. package/src/schemas/presetSchema.ts +2 -32
  53. package/src/schemas/utils/navigation.ts +3 -53
  54. package/src/stores/cart.ts +23 -0
  55. package/src/utils/cart.ts +36 -0
  56. package/tsconfig.json +1 -3
  57. package/src/components/experimental/GalleryVertical.astro +0 -161
  58. package/src/content/pages/overview/content-layer.mdx +0 -128
  59. package/src/content/pages/overview/customization.mdx +0 -83
  60. /package/src/types/{global-props.d.ts → global-props.ts} +0 -0
@@ -1,180 +1,104 @@
1
1
  ---
2
- import Icon from 'fulldev-ui/components/Icon.astro'
2
+ import Element from 'fulldev-ui/components/Element.astro'
3
3
  import Image from 'fulldev-ui/components/Image.astro'
4
4
 
5
- const { images, direction } = Astro.props
5
+ const { images } = Astro.props
6
6
  ---
7
7
 
8
8
  <script>
9
- const carousel = document.querySelector('.gallery .large-carousel')
10
- const icon = document.querySelector('.gallery .icon')
11
- const smallImages = document.querySelectorAll('.gallery .small-image')
12
-
13
- carousel &&
14
- icon?.addEventListener('click', () => {
15
- const carouselWidth = (carousel as HTMLElement).offsetWidth
16
- const currentScroll = carousel.scrollLeft
17
- const maxScroll = carousel.scrollWidth - carouselWidth
18
-
19
- let scrollAmount = currentScroll + carouselWidth
20
- if (scrollAmount > maxScroll) {
21
- scrollAmount = 0 // Reset to beginning if we're at the end
22
- }
23
-
24
- carousel.scrollTo({
25
- left: scrollAmount,
26
- behavior: 'smooth',
27
- })
28
- })
29
-
30
- carousel &&
31
- smallImages?.forEach((image, i) => {
32
- image.addEventListener('click', () => {
33
- const imageWidth = (carousel as HTMLElement).offsetWidth
34
- carousel.scrollTo({
35
- left: i * imageWidth,
36
- behavior: 'smooth',
9
+ const setupGallery = (document: Document) => {
10
+ const galleries = document.querySelectorAll('.gallery')
11
+
12
+ galleries.forEach((gallery) => {
13
+ const carousel = gallery.querySelector('.large-carousel')
14
+ const smallImages = gallery.querySelectorAll('.small-image')
15
+
16
+ carousel &&
17
+ smallImages?.forEach((image, i) => {
18
+ image.addEventListener('click', () => {
19
+ const largeImages = carousel.querySelectorAll('.large-image')
20
+ if (largeImages[i]) {
21
+ largeImages[i].scrollIntoView({
22
+ behavior: 'smooth',
23
+ block: 'nearest',
24
+ inline: 'start',
25
+ })
26
+ }
27
+ })
37
28
  })
38
- })
39
29
  })
30
+ }
31
+
32
+ setupGallery(document)
33
+
34
+ document.addEventListener('astro:before-swap', (event) => {
35
+ setupGallery(event.newDocument)
36
+ })
40
37
  </script>
41
38
 
42
- <div
43
- class:list={[
44
- 'full',
45
- 'gallery',
46
- {
47
- [`direction-${direction}`]: direction,
48
- },
49
- ]}
50
- >
51
- <div class="large-container">
52
- <div class="large-carousel">
53
- {
54
- images?.map((image: any) => (
55
- <Image
56
- class="large-image"
57
- src={image}
58
- />
59
- ))
60
- }
61
- </div>
39
+ <Element class:list={['gallery']}>
40
+ <Element class="large-carousel">
62
41
  {
63
- images?.length > 1 && (
64
- <Icon
65
- class="icon"
66
- name="swipe-left"
42
+ images?.map((image: any) => (
43
+ <Image
44
+ class="large-image"
45
+ {...(typeof image === 'string' ? { src: image } : image)}
67
46
  />
68
- )
47
+ ))
69
48
  }
70
- </div>
71
- <div class="small-carousel">
49
+ </Element>
50
+ <Element class="small-carousel">
72
51
  {
73
52
  images?.length > 1 &&
74
53
  images.map((image: any) => (
75
54
  <Image
76
55
  class="small-image"
77
- src={image}
56
+ {...(typeof image === 'string' ? { src: image } : image)}
78
57
  />
79
58
  ))
80
59
  }
81
- </div>
82
- </div>
60
+ </Element>
61
+ </Element>
83
62
 
84
63
  <style is:global lang="scss">
85
64
  .gallery {
86
65
  display: flex;
87
66
  position: relative;
88
- column-gap: var(--space-4);
89
- row-gap: var(--space-1);
90
67
  flex-direction: column;
91
-
92
- @media (min-width: 1024px) {
93
- flex-direction: row-reverse;
94
- }
95
-
96
- .large-container {
97
- display: flex;
98
- justify-content: space-between;
99
- align-items: center;
100
-
101
- &:hover .icon {
102
- opacity: 1;
103
- }
104
-
105
- .icon {
106
- position: absolute;
107
- right: var(--space-3);
108
- opacity: 0.5;
109
- animation: swipe-icon 1.6s ease-in-out infinite;
110
- transition: opacity 0.2s ease-in-out;
111
- font-size: calc(var(--text-2) * 1.7);
112
-
113
- @media (min-width: 1024px) {
114
- display: none;
115
- }
116
- }
117
-
118
- @keyframes swipe-icon {
119
- 0%,
120
- 100% {
121
- right: var(--space-3);
122
- }
123
- 50% {
124
- right: calc(var(--space-3) * 2);
125
- }
126
- }
127
- }
68
+ gap: var(--space-1) var(--space-4);
128
69
 
129
70
  .small-carousel,
130
71
  .large-carousel {
131
- --column-width: 100%;
132
72
  display: flex;
133
73
  position: relative;
134
- align-items: flex-start;
74
+ align-items: center;
135
75
  gap: var(--space-4);
136
-
137
76
  box-sizing: border-box;
138
77
  padding-bottom: var(--space-4);
139
78
  width: 100%;
140
- overflow-x: auto;
79
+ overflow: auto;
141
80
  scroll-behavior: smooth;
142
81
  scroll-snap-type: x mandatory;
143
82
 
144
- > .root {
83
+ > .image {
145
84
  flex-grow: 0;
146
85
  flex-shrink: 0;
147
86
  width: var(--column-width);
148
87
  scroll-snap-align: center;
149
88
  }
89
+ }
150
90
 
151
- &.position-inset {
152
- margin-right: calc(var(--inner-x) * -1);
153
- margin-left: calc(var(--inner-x) * -1);
154
- padding-right: var(--inner-x);
155
- padding-left: var(--inner-x);
156
- width: calc(100% + var(--inner-x) * 2);
157
- }
91
+ .large-carousel {
92
+ --column-width: 100%;
158
93
  }
159
94
 
160
95
  .small-carousel {
161
96
  --column-width: var(--space-7);
162
97
 
163
- @media (min-width: 1024px) {
164
- --column-width: 100%;
165
-
166
- flex-direction: column;
167
- width: 40%;
98
+ .image:hover {
99
+ opacity: 0.8;
100
+ cursor: pointer;
168
101
  }
169
102
  }
170
-
171
- .small-image,
172
- .large-image {
173
- }
174
-
175
- .small-image:hover {
176
- opacity: 0.8;
177
- cursor: pointer;
178
- }
179
103
  }
180
104
  </style>
@@ -151,6 +151,38 @@ const { as = 'div', ...rest } = Astro.props
151
151
  }
152
152
  }
153
153
 
154
+ ul,
155
+ ol {
156
+ display: flex;
157
+ flex-direction: column;
158
+ margin: var(--space-4) 0;
159
+ padding-left: var(--space-5);
160
+ color: var(--color-11);
161
+ font-size: var(--text-2);
162
+ line-height: 1.625;
163
+ }
164
+
165
+ ul {
166
+ list-style-type: disc;
167
+ }
168
+
169
+ ol {
170
+ list-style-type: decimal;
171
+ }
172
+
173
+ li {
174
+ align-items: center;
175
+ margin-bottom: var(--space-2);
176
+ max-width: calc(var(--space-4) * 44);
177
+ color: var(--color-11);
178
+ font-size: var(--text-2);
179
+ line-height: 1.625;
180
+ }
181
+
182
+ li:last-child {
183
+ margin-bottom: 0;
184
+ }
185
+
154
186
  p code {
155
187
  background-color: var(--base-12);
156
188
  padding: 0 var(--space-1);
@@ -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
@@ -13,8 +13,79 @@ import Product from 'fulldev-ui/blocks/Product.astro'
13
13
  heading="Basic Tee"
14
14
  price={48}
15
15
  rating={5}
16
- image="/images/placeholder-landscape.webp"
17
- buttons={[{ text: 'Add to cart' }]}
16
+ image="placeholder-landscape.webp"
17
+ form={{ submit: 'Add to cart' }}
18
+ description="Oversized white tee made of 100% cotton."
19
+ list={[
20
+ 'Shortsleeve',
21
+ 'Ribbed collar',
22
+ 'Runs large',
23
+ 'Unisex',
24
+ 'Material: 100% cotton',
25
+ 'Imported',
26
+ ]}
27
+ />
28
+ ```
29
+
30
+ ```astro live
31
+ ---
32
+ import Product from 'fulldev-ui/blocks/Product.astro'
33
+ ---
34
+
35
+ <Product
36
+ heading="Basic Tee"
37
+ price={48}
38
+ rating={5}
39
+ images={[
40
+ '/images/blocks/colleagues.png',
41
+ '/images/blocks/content.png',
42
+ '/images/blocks/cta.png',
43
+ '/images/blocks/features.png',
44
+ '/images/blocks/footer.png',
45
+ '/images/blocks/header.png',
46
+ '/images/blocks/hero.png',
47
+ '/images/blocks/intro.png',
48
+ '/images/blocks/posts.png',
49
+ '/images/blocks/prices.png',
50
+ '/images/blocks/reviews.png',
51
+ ]}
52
+ form={{ submit: 'Add to cart' }}
53
+ description="Oversized white tee made of 100% cotton."
54
+ list={[
55
+ 'Shortsleeve',
56
+ 'Ribbed collar',
57
+ 'Runs large',
58
+ 'Unisex',
59
+ 'Material: 100% cotton',
60
+ 'Imported',
61
+ ]}
62
+ />
63
+ ```
64
+
65
+ ```astro live
66
+ ---
67
+ import Product from 'fulldev-ui/blocks/Product.astro'
68
+ ---
69
+
70
+ <Product
71
+ heading="Basic Tee"
72
+ price={48}
73
+ rating={5}
74
+ images={[
75
+ '/images/blocks/colleagues.png',
76
+ '/images/blocks/content.png',
77
+ '/images/blocks/cta.png',
78
+ '/images/blocks/features.png',
79
+ '/images/blocks/footer.png',
80
+ '/images/blocks/header.png',
81
+ '/images/blocks/hero.png',
82
+ '/images/blocks/intro.png',
83
+ '/images/blocks/posts.png',
84
+ '/images/blocks/prices.png',
85
+ '/images/blocks/reviews.png',
86
+ ]}
87
+ gallery="vertical"
88
+ form={{ submit: 'Add to cart' }}
18
89
  description="Oversized white tee made of 100% cotton."
19
90
  list={[
20
91
  'Shortsleeve',
@@ -1,7 +1,5 @@
1
1
  ---
2
2
  presets: [base]
3
- sidebar: false
4
- toc: false
5
3
 
6
4
  seo:
7
5
  title: Fulldev UI - Astro component and block library, open-source
@@ -1,21 +1,14 @@
1
1
  ---
2
- presets: [docs, blocks]
2
+ presets: [docs]
3
3
 
4
4
  title: Layout
5
5
  ---
6
6
 
7
- ```astro live
8
- ---
9
- import Hero from 'fulldev-ui/blocks/Hero.astro'
10
- import Layout from 'fulldev-ui/layouts/Layout.astro'
11
- ---
7
+ import Layout from 'fulldev-ui/layouts/Layout.astro?raw'
8
+ import { Code } from 'astro:components'
9
+
10
+ # Layout
11
+
12
+ The Layout component is used to wrap the content of a page. It provides a structured template for your website.
12
13
 
13
- <Layout>
14
- <Hero
15
- heading="Layout"
16
- text="The Layout component is used to wrap the content of a page."
17
- align="center"
18
- frame="viewport"
19
- />
20
- </Layout>
21
- ```
14
+ <Code code={Layout} lang="astro" />
@@ -1,5 +1,14 @@
1
1
  ---
2
- presets: [docs, blocks]
2
+ presets: [docs]
3
3
 
4
4
  title: DocsLayout
5
5
  ---
6
+
7
+ import Layout from 'fulldev-ui/layouts/DocsLayout.astro?raw'
8
+ import { Code } from 'astro:components'
9
+
10
+ # DocsLayout
11
+
12
+ The DocsLayout component is used to wrap the content of a page in a sidebar and a main content area and table of contents.
13
+
14
+ <Code code={Layout} lang="astro" />
@@ -68,3 +68,8 @@ import Button from 'fulldev-ui/components/Button.astro'
68
68
 
69
69
  {/* This will render a button */}
70
70
  <Button if={true} />
71
+ ```
72
+
73
+ ## Overriding Components
74
+
75
+ You can override components by creating a new component with the same name as one from the library in the **src/components** directory and adding your custom code. This also works for blocks and layouts.
@@ -0,0 +1,139 @@
1
+ ---
2
+ presets: [docs]
3
+ title: Content Collections
4
+ ---
5
+
6
+ import Link from 'fulldev-ui/components/Link.astro'
7
+
8
+ # Content Collections
9
+
10
+ We utilize <Link href="https://docs.astro.build/docs/guides/content-collections/">Astro's Content Layer</Link> to create entire websites using just content files and our components.
11
+
12
+ ## Starter Template
13
+
14
+ This is the recommended way to get started with our content layer integration. We've created a <Link href="https://github.com/fulldotdev/starter/tree/main">starter template</Link> with examples of everything you need to get started.
15
+
16
+ ```bash
17
+ pnpm create astro@latest -- --template fulldotdev/starter
18
+ ```
19
+
20
+ ## Manual Setup
21
+
22
+ To get started with the manual setup, you need to install the <Link href="/overview/installation/">integration</Link> and add `injectRoutes: true` to your `astro.config.ts` file, see <Link href="#type-safe-frontmatter">frontmatter</Link> below for more information on how this generates a site using content files.
23
+
24
+ ```ts
25
+ import { defineConfig } from 'astro/config'
26
+ import fulldev from 'fulldev-ui/integration'
27
+
28
+ // https://astro.build/config
29
+ export default defineConfig({
30
+ integrations: [
31
+ fulldev({
32
+ // other options
33
+ injectRoutes: true,
34
+ }),
35
+ ],
36
+ })
37
+ ```
38
+
39
+ ## Type-safe frontmatter
40
+
41
+ Each file has a few frontmatter objects that are important to know about. Seo has priority over title and description, however title and description is used in multiple places like a card.
42
+
43
+ ```yml
44
+ ---
45
+ preset: [docs] # Applies the configuration from src/content/presets/docs.yml
46
+ component: DocsLayout
47
+
48
+ seo:
49
+ title: Page Title
50
+ description: This is my page description
51
+ image: /image.jpg # Open Graph Image
52
+
53
+ # Information on the page, this is used in places like card, sidebar, etc.
54
+ title: Page Title
55
+ description: This is my page description
56
+
57
+ sections: # Here you generate the page by adding a component and passing props
58
+ - component: Hero
59
+ heading: Page Title
60
+ text: This is my page description
61
+ buttons:
62
+ - text: Button
63
+ color: brand
64
+ href: /
65
+ - text: Button
66
+ href: /
67
+ ---
68
+ # This is the prose, you can use markdown here
69
+ ```
70
+
71
+ For all objects avaliable in the Content Layer, see the <Link href="https://ui.full.dev/schemas/page/">schemas</Link>.
72
+
73
+ ### Presets
74
+
75
+ Presets are configuration files that can be used to set the default values for a page. They are located in the **src/content/presets** directory and you can use them by adding the `preset` property to the frontmatter of a page or add a `basePreset` to the integration setup in the `astro.config.ts` file.
76
+
77
+ ```ts
78
+ import { defineConfig } from 'astro/config'
79
+ import fulldev from 'fulldev-ui/integration'
80
+
81
+ // https://astro.build/config
82
+ export default defineConfig({
83
+ integrations: [
84
+ fulldev({
85
+ // other options
86
+ basePreset: 'base', // Applies the configuration from src/content/presets/base.yml to every page
87
+ }),
88
+ ],
89
+ })
90
+ ```
91
+
92
+ ## i18n
93
+
94
+ Getting started with i18n is easy, you can easily add additional languages by creating a new folder named after a language code in the **content/pages** directory and adding your content files in the new language.
95
+
96
+ These pages are just as static as the others however you can merge them with the default language by adding the `i18n` key to the frontmatter.
97
+
98
+ By merging pages you only need to specify the content that is different for the new language. Things like images do not need to be repeated in these new files. See example:
99
+
100
+ content/pages/index.md:
101
+
102
+ ```md
103
+ ---
104
+ sections:
105
+ - component: Hero
106
+ image: /image.webp
107
+ heading: Page Title
108
+ text: This is my page description
109
+ ---
110
+ ```
111
+
112
+ content/pages/nl/index.md:
113
+
114
+ ```md
115
+ ---
116
+ i18n: index
117
+
118
+ sections:
119
+ - component: Hero
120
+ heading: Page Title
121
+ text: This is my page description
122
+ ---
123
+ ```
124
+
125
+ These return the same results
126
+
127
+ ### Example structure
128
+
129
+ ```bash
130
+ .
131
+ ├── src/
132
+ │ ├── content/
133
+ │ │ ├── pages/
134
+ │ │ │ ├── index.md
135
+ │ │ │ ├── nl/
136
+ │ │ │ │ └── index.md
137
+ │ │ │ └── de/
138
+ │ │ │ │ └── index.md
139
+ ```
@@ -7,7 +7,21 @@ import Link from 'fulldev-ui/components/Link.astro'
7
7
 
8
8
  # Installation
9
9
 
10
- Install fulldev-ui with your favorite package manager and you are ready to go.
10
+ You can add fulldev-ui to your project, or use the starter template.
11
+
12
+ ## Add to existing project
13
+
14
+ ### Automatic setup
15
+
16
+ Use the astro add command to automatically install the dependencies and add the integration.
17
+
18
+ ```bash
19
+ npx astro add fulldev-ui
20
+ ```
21
+
22
+ ## Manual installation
23
+
24
+ Install fulldev-ui with your favorite package manager.
11
25
 
12
26
  ```bash
13
27
  pnpm i fulldev-ui
@@ -19,36 +33,21 @@ yarn add fulldev-ui
19
33
  npm i fulldev-ui
20
34
  ```
21
35
 
22
- ## Integration
23
-
24
- To install the integration, import it in your `astro.config.ts` file.
25
- You can optionally add a custom css file and define custom colors and other theming options, see the <Link href="/overview/customization/">customization documentation</Link> for more information.
26
-
27
- To get started with the content layer, see the <Link href="/overview/content-layer/#manual-setup">content layer documentation</Link>.
36
+ Then setup the integration in your `astro.config.ts` file.
28
37
 
29
38
  ```ts
30
39
  import { defineConfig } from 'astro/config'
31
40
  import fulldev from 'fulldev-ui/integration'
32
41
 
33
- // https://astro.build/config
34
42
  export default defineConfig({
35
- integrations: [
36
- fulldev({
37
- css: '/src/css/custom.css',
38
- colors: {
39
- theme: 'dark',
40
- dark: {
41
- background: '#111110',
42
- base: '#6F6D66',
43
- brand: '#F50',
44
- },
45
- light: {
46
- background: '#EEEEEC',
47
- base: '#6F6D66',
48
- brand: '#F50',
49
- },
50
- },
51
- }),
52
- ],
43
+ integrations: [fulldev()],
53
44
  })
54
45
  ```
46
+
47
+ ## Using the starter template
48
+
49
+ The easiest way to get started is to use the [starter template](https://github.com/fulldotdev/starter).
50
+
51
+ ```bash
52
+ pnpm create astro@latest -- --template fulldotdev/starter
53
+ ```