Skip to content

Commit

Permalink
Merge branch 'individual-state' into storybook
Browse files Browse the repository at this point in the history
  • Loading branch information
tpluscode committed Dec 3, 2024
2 parents 4177e14 + f508a9e commit ee73c2f
Show file tree
Hide file tree
Showing 127 changed files with 36,330 additions and 1,409 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilled-feet-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hydrofoil/shaperone-wc": minor
---

Removed the `window.Shaperone.DEBUG` flag in favor of component `debug` property
6 changes: 6 additions & 0 deletions .changeset/quiet-fireants-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@hydrofoil/shaperone-core": patch
"@hydrofoil/shaperone-wc": patch
---

Improved state management by separating the state of each element instance
29 changes: 29 additions & 0 deletions .changeset/wild-icons-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
"@hydrofoil/shaperone-wc": minor
---

Big change how elements are configured. Global config can be set using the `configure.js` module.

```js
import { configure } from '@hydrofoil/shaperone-wc'

await configure(({ components, editors, renderer, validation }) => {

})
```

Additionally, each component can be customised further by providing calling `configure` method of the component.

```html
<shaperone-form></shaperone-form>

<script type="module">
import { configure } from '@hydrofoil/shaperone-wc'
// global configuration must always be invoked
configure()
document.querySelector('shaperone-form').configure(({ components, editors, renderer, validation }) => {
})
</script>
```
176 changes: 93 additions & 83 deletions demos/lit-html/src/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DescriptionTooltip } from '@hydrofoil/shaperone-playground-examples/Des
import * as vaadinComponents from '@hydrofoil/shaperone-wc-vaadin/components.js'
import * as shoelaceComponents from '@hydrofoil/shaperone-wc-shoelace/components.js'
import { settings as shoelaceSettings } from '@hydrofoil/shaperone-wc-shoelace/settings.js'
import type { ConfigCallback } from '@hydrofoil/shaperone-wc/configure.js'
import { configure } from '@hydrofoil/shaperone-wc/configure.js'
import { dash } from '@tpluscode/rdf-ns-builders'
import type { Decorate, RenderTemplate } from '@hydrofoil/shaperone-wc/templates.js'
Expand All @@ -25,30 +26,53 @@ import type { RendererState } from './state/models/renderer.js'
setBasePath('https://unpkg.com/@shoelace-style/shoelace/dist')
shoelaceSettings.hoist = false

const { editors, components, validation, renderer } = await configure($rdf)

export const componentSets: Record<ComponentsState['components'], Record<string, Component>> = {
native: { ...nativeComponents, starRating },
material: { ...nativeComponents, ...mwcComponents, languages: LanguageSelect.component('material'), starRating },
vaadin: { ...nativeComponents, ...vaadinComponents, languages: LanguageSelect.component('lumo'), starRating },
shoelace: { ...nativeComponents, ...shoelaceComponents, starRating },
}

editors.addMetadata(env => [...LanguageSelect.metadata(env), ...StarRating.metadata(env)])
editors.addMatchers({
languages: LanguageSelect.matcher,
starRating: StarRating.matcher,
})
shaperoneHydra({ editors, components })
components.decorate(DescriptionTooltip)
function * focusNodeDecorators(labs: RendererState['labs']) {
if (labs?.xone) {
yield xone.focusNode
}
if (labs?.errorSummary) {
yield errorSummary
}
yield MaterialRenderStrategy.focusNode
}

let focusNodeTemplate = templates.focusNode

validation.setValidator(validate)
const initialRenderStrategy = {
...templates,
...MaterialRenderStrategy,
focusNode: [...focusNodeDecorators({})].reduce(combineDecorators, focusNodeTemplate),
}

configure($rdf, ({ editors, components, validation, renderer }) => {
editors.addMetadata(env => [...LanguageSelect.metadata(env), ...StarRating.metadata(env)])
editors.addMatchers({
languages: LanguageSelect.matcher,
starRating: StarRating.matcher,
})
shaperoneHydra({
editors,
components,
})
components.decorate(DescriptionTooltip)

validation.setValidator(validate)

renderer.setTemplates(initialRenderStrategy)
})

export const selectComponents = (() => {
let currentComponents = componentSets.native
let previousComponents: ComponentsState['components'] | undefined

return (name: ComponentsState['components']) => {
return (name: ComponentsState['components']): ConfigCallback => ({ components }) => {
if (previousComponents === name) return
previousComponents = name

Expand All @@ -64,91 +88,77 @@ function combineDecorators<Template extends RenderTemplate>(combined: Template,
}

export const configureRenderer = (() => {
function * focusNodeDecorators(labs: RendererState['labs']) {
if (labs?.xone) {
yield xone.focusNode
}
if (labs?.errorSummary) {
yield errorSummary
}
yield MaterialRenderStrategy.focusNode
}

let focusNodeTemplate = templates.focusNode

const initialStrategy = {
...templates,
...MaterialRenderStrategy,
focusNode: [...focusNodeDecorators({})].reduce(combineDecorators, focusNodeTemplate),
}

renderer.setTemplates(initialStrategy)

let previousNesting: RendererState['nesting']
let previousGrouping: RendererState['grouping']
let previousLabs: RendererState['labs']

return {
async switchNesting({ nesting }: RendererState) {
if (previousNesting === nesting) return
previousNesting = nesting

if (nesting === 'always one') {
const { topmostFocusNodeFormRenderer } = await import('@hydrofoil/shaperone-playground-examples/NestedShapesIndividually/renderer.js')
const nestingComponents = await import('@hydrofoil/shaperone-playground-examples/NestedShapesIndividually/components.js')

renderer.setTemplates({
form: topmostFocusNodeFormRenderer(initialStrategy.form),
})
components.pushComponents(nestingComponents)
} else if (nesting === 'inline') {
const nestingComponents = await import('@hydrofoil/shaperone-playground-examples/InlineNestedShapes')
components.pushComponents(nestingComponents)
} else {
renderer.setTemplates({ form: initialStrategy.form })
components.removeComponents([dash.DetailsEditor])
switchNesting({ nesting }: RendererState): ConfigCallback {
return async ({ renderer, components }) => {
if (previousNesting === nesting) return
previousNesting = nesting

if (nesting === 'always one') {
const { topmostFocusNodeFormRenderer } = await import('@hydrofoil/shaperone-playground-examples/NestedShapesIndividually/renderer.js')
const nestingComponents = await import('@hydrofoil/shaperone-playground-examples/NestedShapesIndividually/components.js')

renderer.setTemplates({
form: topmostFocusNodeFormRenderer(initialRenderStrategy.form),
})
components.pushComponents(nestingComponents)
} else if (nesting === 'inline') {
const nestingComponents = await import('@hydrofoil/shaperone-playground-examples/InlineNestedShapes')
components.pushComponents(nestingComponents)
} else {
renderer.setTemplates({ form: initialRenderStrategy.form })
components.removeComponents([dash.DetailsEditor])
}
}
},

async switchLayout({ grouping, labs }: RendererState) {
if (previousGrouping === grouping) return
previousGrouping = grouping

const strategy = {
focusNode: initialStrategy.focusNode,
group: initialStrategy.group,
switchLayout({ grouping, labs }: RendererState): ConfigCallback {
return async ({ renderer }) => {
if (previousGrouping === grouping) return
previousGrouping = grouping

const strategy = {
focusNode: initialRenderStrategy.focusNode,
group: initialRenderStrategy.group,
}

if (grouping === 'vaadin accordion') {
const {
AccordionGroupingRenderer,
AccordionFocusNodeRenderer,
} = await import('@hydrofoil/shaperone-wc-vaadin/renderer/accordion.js')

strategy.group = AccordionGroupingRenderer
focusNodeTemplate = AccordionFocusNodeRenderer
} else if (grouping === 'material tabs') {
const {
TabsGroupRenderer,
TabsFocusNodeRenderer,
} = await import('@hydrofoil/shaperone-wc-material/renderer/tabs.js')

strategy.group = TabsGroupRenderer
focusNodeTemplate = TabsFocusNodeRenderer
}

strategy.focusNode = [...focusNodeDecorators(labs)].reduce(combineDecorators, focusNodeTemplate)
renderer.setTemplates(strategy)
}

if (grouping === 'vaadin accordion') {
const {
AccordionGroupingRenderer,
AccordionFocusNodeRenderer,
} = await import('@hydrofoil/shaperone-wc-vaadin/renderer/accordion.js')

strategy.group = AccordionGroupingRenderer
focusNodeTemplate = AccordionFocusNodeRenderer
} else if (grouping === 'material tabs') {
const {
TabsGroupRenderer,
TabsFocusNodeRenderer,
} = await import('@hydrofoil/shaperone-wc-material/renderer/tabs.js')

strategy.group = TabsGroupRenderer
focusNodeTemplate = TabsFocusNodeRenderer
}

strategy.focusNode = [...focusNodeDecorators(labs)].reduce(combineDecorators, focusNodeTemplate)
renderer.setTemplates(strategy)
},

async setLabs({ labs }: RendererState) {
if (JSON.stringify(previousLabs) === JSON.stringify(labs)) return
setLabs({ labs }: RendererState): ConfigCallback {
return ({ renderer }) => {
if (JSON.stringify(previousLabs) === JSON.stringify(labs)) return

previousLabs = labs
previousLabs = labs

renderer.setTemplates({
focusNode: [...focusNodeDecorators(labs)].reduce(combineDecorators, focusNodeTemplate),
})
renderer.setTemplates({
focusNode: [...focusNodeDecorators(labs)].reduce(combineDecorators, focusNodeTemplate),
})
}
},
}
})()
8 changes: 4 additions & 4 deletions demos/lit-html/src/shaperone-playground-lit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,10 @@ export class ShaperonePlayground extends connect(store(), LitElement) {
}

mapState(state: State) {
selectComponents(state.componentsSettings.components)
configureRenderer.switchLayout(state.rendererSettings)
configureRenderer.switchNesting(state.rendererSettings)
configureRenderer.setLabs(state.rendererSettings)
this.form.configure(selectComponents(state.componentsSettings.components))
this.form.configure(configureRenderer.switchLayout(state.rendererSettings))
this.form.configure(configureRenderer.switchNesting(state.rendererSettings))
this.form.configure(configureRenderer.setLabs(state.rendererSettings))

return {
components: state.componentsSettings,
Expand Down
10 changes: 2 additions & 8 deletions demos/lit-html/src/state/store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ModelStore, StoreDispatch, StoreState } from '@captaincodeman/rdx'
import { createStore, devtools, persist } from '@captaincodeman/rdx'
import { createStore, persist } from '@captaincodeman/rdx'
import { config } from './config.js'

export type State = StoreState<typeof config>
Expand Down Expand Up @@ -44,11 +44,5 @@ export const store = (() => {
},
})

return () => {
if (window.Shaperone?.DEBUG === true) {
return devtools(store)
}

return store
}
return () => store
})()
72 changes: 72 additions & 0 deletions dist/storybook/animations/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Shoelace Animations

Your favorite [animate.css](https://animate.style/) effects available as ES modules for use with the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API).

- 🏆 ~100 quality animations
- 🎾 ~30 popular easings
- 🚚 Works with CDNs
- 🌲 Fully tree-shakeable

[Try it on JSFiddle](https://jsfiddle.net/claviska/ohjmkgb1)

This module was built for [Shoelace](https://shoelace.style/), but it works well as a stand-alone library too!

## Installation

```bash
npm install @shoelace-style/animations
```

## Usage

Importing all animations:

```js
import * as animations from '@shoelace-style/animations';
```

Importing individual animations:

```js
import { bounce } from '@shoelace-style/animations';
```

Importing easings:

```js
import { easings } from '@shoelace-style/animations';
```

Animating an element:

```html
<div style="display: block; width: 100px; height: 100px; background: tomato; margin: 2rem;"></div>

<script type="module">
import { easings, flip } from 'https://cdn.jsdelivr.net/npm/@shoelace-style/animations@1/dist/index.js';
const box = document.querySelector('div');
box.animate(flip, {
duration: 1500,
iterations: Infinity,
easing: easings.easeInSine
});
</script>
```

This example uses the [jsDelivr CDN](https://www.jsdelivr.com/). To import the library locally, install it and make `node_modules/@shoelace-style/animations/dist` available to your app or bundler.

## Developers

This script parses all animation stylesheets found in `node_modules/animate.css` and generates [keyframe objects](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats) that you can use with the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API). As animations are tweaked and added to animate.css, the keyframes herein will be kept in sync when rerunning the script.

To build the project, run:

```bash
npm run build
```

This will purge and rebuild the `dist` directory.

Please report all bugs and suggestions to [the issue tracker](https://github.com/shoelace-style/animations/issues).
Loading

0 comments on commit ee73c2f

Please sign in to comment.