We want to decouple schema stored in db from sdk which generates a list
of components. Components will be added dynamically later so better
avoid component name enum.
After discussing with @kof figured we do not need to store preset styles
in db as after sdk upgrade components may still break.
Sdk versioning along with its hardcoded values will solve the problem
better.
Found zod allows to pass anything in transform without type checking.
This means we can easily get unexpected result. In this case we could
get undefined as asset.
As a solution I defined two versions of types, client side and stored in
db. Conversion is implemented on db routes side.
This makes data flow more clear and let us describe only two versions of
types instead of tree (in, out, client side).
Here is migration to new props type with more safe conversion to db
format. Added two versions StoredPropsItem for and PropsItem for client
and got rid of "as" casting.
InstanceProps is designed to store props per each instance which
requires a lot of sql updates on every props change.
Here moved per instance props into array with props for whole tree. This
way patches are safer to apply on large trees.
```
type PropsItem = {
id: string,
instanceId: string,
name: string,
required?: boolean,
type: 'number' | 'string' | 'boolean' | 'asset',
value: number | string | boolean
}
```
Props have a lot of logic to synchronize values. And after moving
updates into designer we get fresh state instantly and can simplify the
logic even more.
Turns out we store whole db representation in each props each per
instance item. This is wasteful and increase complexity of code.
```
{
[InstanceId]: {
id: UUID,
instanceId: InstanceId,
treeId: TreeId,
props: UserProp[]
}
}
```
Where instance id is duplicated and tree id is provided as patch
context. Id can be replaced with combination of instance id and tree id.
```
{
[InstanceId]: UserProp[]
}
```
Ref https://github.com/nanostores/nanostores
Nanostores is another open source implementation of reactive states.
Supports a lot of frameworks and provides useful utilities like computed
stores. Api is slightly different
```
store.get(): Value
store.set(value: Value)
```
`useStore` resolves only value so I temporary added custom `useValue` to
not rewrite whole project. Since we gonna use computed atoms it makes
more sense to invoke useStore where atom value is used instead of
reusable hook.
Ref https://github.com/webstudio-is/webstudio-designer/issues/696
Migrated updating and rendering to normalized styles. There are still a
few cases to migrate so left legacy root instance updates.
Styles are updated with immerhin consistently with whole project.
Can be tested changing styles and deleting breakpoints.
Ref https://github.com/webstudio-is/webstudio-designer/issues/696
Gradually starting to migrate to new styles format. Here replaced
getCssRules and getPresetStylesMap with getStyleRules and
getPresetStyleRules utilities.
Will reuse both at once on release.
Ref https://github.com/webstudio-is/webstudio-designer/issues/696
Here only migration and transforms for load and patch. Styles have the
following type and stored in Tree.styles column.
```
Array<{
breakpointId: string,
instanceId: string,
property: StyleProperty,
value: StyleValue
}>
```
Did migration with cursor pagination with 1000 trees per transaction.
Before we populated preset style on instance creation. This does not let
us to distinct preset style from local one.
As an option we could use preset style hardcoded in meta though this may
affect user when we change defaults.
Here I added presetStyle column in Tree table with the list of styles
for component.
```
Array<{
component: string,
property: string,
value: StyleValue
}>
```
Will style controls as grey for such styles.
Ref https://github.com/webstudio-is/webstudio-designer/issues/366
Parsed initial values to get correct unit instead of px for some
properties. There is still edge case with unitless values I'm gonna fix
in another PR.
Also bumped mdn-data and removed overrides fixed on mdn side.
## Description
Somehow we forgot to add object-position
## Steps for reproduction
1. select instance
2. go to sizes section in style panel
## Code Review
- [ ] hi @istarkov I need you to do
- conceptual review (architecture, feature-correctness)
## Before requesting a review
- [x] made a self-review
- [x] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio-designer/blob/main/apps/designer/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `designer/env-check.js` if mandatory
Ref https://github.com/webstudio-is/webstudio-designer/issues/651
We want to normalize our tree structure and need to distinct text
children with ids. Now instead of string its respresented as
```
{
type: 'text',
value: string
}
```
This also gives us a little type safety because typeof child ===
'string' ignores when child cannot be string.
pnpm prevents access to jest and @types/jest from packages so we need to
explicitly install it. Though @types/jest is not officially maintained
and often late for months with new major which bloats node_modules with
two versions of jest transitives.
Here is alternative way to use official types. The only downside is
complains these types has less descriptions.
Ref https://github.com/webstudio-is/webstudio-designer/issues/598
When tracking selected element from the root it's hard to get current
element which can be changed with props.
One more issue is storing element in state doubles amount of renders and
in selected instance logic we have a chain of state -> effect -> state
-> effect cases.
Here I store element in ref so we avoid rerender when set element to
state. Then tracked element rect is not written to state and sent to
designer directly.
Since the effect is unmounted along with element we do not need to use
mutation observer to track parent changes and can just recompute rect on
remount.
Will help with
https://github.com/webstudio-is/webstudio-designer/issues/628
treeId is stored in every props update which complicates data flow and
requires passing it everywhere. Here I instead pass it inside of
transaction.
This allowed us pass undefined in props data when select instance so we
no longer need to create empty instance props. Updates will create it
lazily.
## Before requesting a review
- [ ] if the PR is WIP - use draft mode
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
- [ ] what kind of review is needed?
- [ ] conceptual
- [ ] detailed
- [ ] with testing
## Test cases
- [ ] step by step interaction description and what is expected to
happen
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio-designer/blob/main/apps/designer/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `designer/env-check.js` if mandatory
Right now our build and CI take a lot of time. 1:40min - 2min on CI and
1min locally. We spend time on vercel, on main CI, on publish and
locally.
At the moment in packages anything outside of src folder is not checked
because of rootDir.
We have to generate "references" field on precommit.
All these issues can be avoided if remove .d.ts generation completely
and specify sources in "types" field. This way we get zero build time
for types and can switch to other build tool (like esbuild) for .js
generation and get almost instant build on vercel, on main CI and on
publish.
Downsides
- it can be slower (actually not really caz we delete .tsbuildinfo cache
anyway and we can still generate it with incremental flag)
- it contraditcs recommended practices for published packages (we can
generate .d.ts in publish script only and use "types" as source
internally)
meta props are moved to *.ws.ts
Component removed from *.ws.ts
This allows to merge ws props with registered components props
`registerComponents` now are
- registerComponents(customComponents);
- registerComponentsMeta(customComponentsMeta);
_(Splitting will allow for code splitting to work.)_
Removal of `Component` (and then `Icon` prop) would allow serializing
*.ws.ts metadata between iframe and app designer
Next PR:
Move Icon into base64 or like.
publish/subscribe ws meta of registered components, so it can be reused
on the Designer side
I need this to pass props of registered components to Designer.
Boolean flags may have a lot of combinations which can lead to
unexpected bugs. Better approach is to categorize nodes with specific
behaviours.
Here I added 5 types
- container - can accept other components with dnd
- control - usually form controls like inputs, without children
- embed - images, videos or other embeddable components, without
children
- rich-text - can be edited on double click
- rich-text-child - formatted text fragment, not listed in components
list
Droppable link an link created in text editor have different
requirements. We should split them. In the next PR they will get
different types so we will avoid similar issues in the future.