├── .github
└── logo.png
├── .gitignore
├── LICENSE
├── README.md
├── ROADMAP.md
├── dist.sh
├── docs
├── README.md
├── api.md
├── getting_started.md
├── installation.md
└── reactivity
│ ├── README.md
│ ├── computed.md
│ ├── conditionals.md
│ ├── directives.md
│ ├── mark.md
│ └── reactive_values.md
├── example
└── 01
│ ├── README.md
│ └── index.html
├── index.ts
├── package.json
├── postpub.sh
├── pubwebsite.sh
├── setup.sh
├── tests
├── index.html
├── templates.html
├── test.computed.html
├── test.conditionals.html
├── test.css
├── test.directives.html
├── test.html
├── test.js
├── test.loops.html
└── test.templates.html
├── tsconfig.json
├── website
├── assets
│ ├── banner.png
│ ├── fonts
│ │ ├── press-start-2p-latin-ext.woff2
│ │ ├── press-start-2p-latin.woff2
│ │ ├── vt323-latin-ext.woff2
│ │ └── vt323-latin.woff2
│ ├── grid.svg
│ ├── heart.png
│ ├── index.css
│ ├── noise.png
│ └── sb.png
├── index.html
├── index.js
└── inventory.html
└── yarn.lock
/.github/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/18alantom/strawberry/488c9ba5d1b2a32d7d991f5d7454f9337e141df4/.github/logo.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /index.js
3 | /index.html
4 | /perf.html
5 | /temp
6 | **/temp.*
7 | notes.md
8 | /dist
9 |
10 | **/*.min.js
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2023-present, Alan Tom
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > [!IMPORTANT]
2 | >
3 | > After nearly 2 years of no commits. I've decided to archive Strawberry.
4 | > Should you be curious enough to wonder why, here's a post on [why it started, why it stopped, any why the decision was made](https://18alan.space/posts/archiving-strawberry.html).
5 |
6 |
7 |
8 |
9 |
10 | Zero-dependency, build-free framework for the artisanal web.
11 |
12 | [Website](https://18alan.space/strawberry/) · [How it works](https://18alan.space/posts/how-hard-is-it-to-build-a-frontend-framework.html) · [Docs](https://github.com/18alantom/strawberry/tree/main/docs)
13 |
14 |
15 |
16 | > **Warning**
17 | >
18 | > Strawberry is in an experimental phase. Everything stated below works, but I
19 | > am still figuring out the quickest and cleanest ways of doing things.
20 |
21 | ---
22 |
23 | > Seriously, another frontend framework?
24 |
25 | Yes, but, Strawberry is not like the usual frontend-framework.
26 |
27 | It doesn't have any dependencies. It doesn't need a build-step to run. It's
28 | tiny, less than 3KB when gzipped. Yet it does a lot of the core things the big,
29 | spangly frameworks can do.
30 |
31 | ```html
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 | A plum colored p element!
44 |
45 |
46 |
49 | ```
50 |
51 | [Here's](https://18alan.space/strawberry/#inventory-example) a live example from
52 | the website.
53 |
54 | ---
55 |
56 |
65 |
66 | **Documentation Index**
67 |
68 | 1. [Installation](./docs/installation.md): explains how to pull Strawberry code into your web project.
69 | 2. [Getting Started](./docs/getting_started.md): describes a simple example with code walk through.
70 | 3. [Reactivity](./docs/reactivity/README.md): explains what is reactivity in Strawberry.
71 | 1. [Reactive Values](./docs/reactivity/reactive_values.md): explains keys and values of the reactive object.
72 | 2. [Mark (`sb-mark`)](./docs/reactivity/mark.md): explains how to mark an element to update along with data.
73 | 3. [Conditionals (`sb-if`, `sb-ifnot`)](./docs/reactivity/conditionals.md): explains how to render or hide an element when data changes to truthy or falsy.
74 | 4. [Computed](./docs/reactivity/computed.md): explains how to define reactive values that depend on other reactive values.
75 | 5. [Directives](./docs/reactivity/directives.md): explains how to extend Strawberry with custom directives.
76 | 4. Composability (to be added)
77 | 5. [API](./docs/api.md): lists all of Strawberry's defined directives and methods.
78 |
79 | ## Installation
80 |
81 | If you wanna try it out, then run this 👇 command to setup a simple _starter_ page.
82 |
83 | ```bash
84 | curl -so- https://raw.githubusercontent.com/18alantom/strawberry/main/setup.sh | bash
85 | ```
86 |
87 | Or if you wanna just use it straight away, copy this 👇 script tag in the head of your html file:
88 |
89 | ```html
90 |
91 | ```
92 |
93 | ## Features
94 |
95 | Here're are a few of its features:
96 |
97 | 1. **Reactivity**: change your data and the UI updates.
98 | 2. **Composability**: create and use components.
99 | 3. **Build-free**: doesn't require a build-step. Link or [copy the lib](https://unpkg.com/sberry@0.0.3-alpha.0/dist/sb.min.js) and you're ready to go.
100 | 4. **Zero Dependencies**: has no dependencies. Uses WebAPIs for everything.
101 | 5. **Tiny**: [source code](https://github.com/18alantom/strawberry/blob/main/index.ts) is under 1000 CLOC.
102 | 6. **No VDOM**: directly updates the DOM.
103 |
104 | Strawberry is and will be developed with these two hard constraints:
105 |
106 | 1. Zero dependencies.
107 | 2. No build step required to run it.
108 |
109 | Other than this, there is also a soft constraint of keeping the source code light.
110 |
111 | ---
112 |
113 | ## Examples
114 |
115 | Here are a couple of simple examples of a few things that Strawberry can do
116 | right now.
117 |
118 | **1. Basic Reactivity**: `innerText` is updated when `data.message` when
119 | is set.
120 |
121 | ```html
122 |
Placeholder
123 |
124 |
127 | ```
128 |
129 | **2. Computed Values**: `innerText` is updated with the computed value
130 | `data.countMessage` when `data.count` is updated.
131 |
132 | ```html
133 |
Placeholder
134 |
135 |
141 | ```
142 |
143 | **3. Conditional Rendering**: `p` is rendered only when `data.sayHi` is `true`.
144 |
145 | ```html
146 |
147 |
Hi!
148 |
149 |
150 |
153 | ```
154 |
155 | **4. Looping**: `ul` is populated with `li` when `data.list` is set. `innerText`
156 | of the `li` are set from the list items.
157 |
158 | ```html
159 |
160 |
161 |
162 |
163 |
166 | ```
167 |
168 | **5. Templates**: On running `sb.register`, the `red-p` element is defined and can be used.
169 |
170 | ```html
171 |
172 |
173 |
174 |
175 | Hi!
176 | ```
177 |
178 | **5. External Templates**: Templates can be defined in external files. They are loaded and registered using `sb.load`.
179 |
180 | ```html
181 |
184 |
185 | Hi!
186 | ```
187 |
188 | **6. Nested Templates**: Templates can be nested, named slots can be used to
189 |
190 | ```html
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
223 | ```
224 |
225 | ---
226 |
227 | ## Development
228 |
229 | The development of Strawberry does has a direction, but no deadlines as I work
230 | on this usually during the weekends.
231 |
232 | Here's a
233 | [road map](https://github.com/18alantom/strawberry/blob/main/ROADMAP.md). This
234 | isn't exactly a road map, but a list of problems and maybe their solutions that
235 | need to be implemented to further Strawberry.
236 |
237 | ### Running Dev Mode
238 |
239 | Strawberry has only two dev dependencies: `esbuild` and `typescript`.
240 |
241 | To run Strawberry in dev mode:
242 |
243 | ```bash
244 | # Clone the repo
245 | git clone https://github.com/18alantom/strawberry
246 |
247 | # Install esbuild and typescript
248 | cd strawberry
249 | yarn install
250 |
251 | # Run in Dev mode
252 | yarn dev
253 | ```
254 |
255 | You can now create an HTML file in the repository and add `script:src` to link
256 | the generated `index.js` file. You can serve this using the Live Preview plugin.
257 |
258 | To view the rendered HTML you need to serve it locally for that you can use the [Live Preview](https://marketplace.visualstudio.com/items?itemName=ms-vscode.live-server) VSCode plugin, or run [this](https://docs.python.org/3/library/http.server.html#:~:text=python%20%2Dm%20http.server%20%2D%2Dbind%20127.0.0.1):
259 |
260 | ```bash
261 | # Cd into strawberry root
262 | cd strawberry
263 |
264 | # Run simple python server to serve files in strawberry
265 | python -m http.server 8080 --bind 127.0.0.1
266 | ```
267 |
268 | ### Tests
269 |
270 | Right now tests just involve linking strawberry to an html file (`test.*.html`),
271 | and calling the `test` function to check whether a value is as expected. Success
272 | and Failures are printed in the console.
273 |
274 | See [`test.html`](https://github.com/18alantom/strawberry/blob/main/tests/test.html) for an example.
275 |
276 | To see all tests in one place, open `test/index.html`.
277 |
278 | ### Website
279 |
280 | The website has two dependencies required to run, `sb.min.js` and
281 | `highlight.min.js` for running strawberry in the example and highlighting all the code.
282 |
283 | You can run the [`pubwebsite.sh`](https://github.com/18alantom/strawberry/blob/main/pubwebsite.sh) script which downloads these files:
284 |
285 | ```bash
286 | ./pubwebsite.sh
287 | ```
288 |
289 | And then respond with `"n"` when it asks to publish:
290 |
291 | ```bash
292 | $ Publish the website? [y/n]: n
293 | $ /Users/you/Desktop/projects/strawberry
294 | ```
295 |
296 | After the script has run, [`website/index.html`](https://github.com/18alantom/strawberry/blob/main/website/index.html) should render as expected.
297 |
298 | ---
299 |
300 | ## Douglas Crockford on the XML of today
301 |
302 | These are excerpts from the CoRecursive podcast on [JSON vs XML](https://corecursive.com/json-vs-xml-douglas-crockford/).
303 |
304 | > It’s probably the JavaScript frameworks. They have gotten so big and so weird.
305 | > People seem to love them. I don’t understand why.
306 |
307 | And on web APIs.
308 |
309 | > ...the browsers have actually gotten pretty good. The web standards thing have
310 | > finally worked, and the web API is stable pretty much. Some of it’s still pretty
311 | > stupid, but it works and it’s reliable.
312 |
313 | Read the transcript on [CoRecursive](https://corecursive.com/json-vs-xml-douglas-crockford/#javascript-frameworks).
314 |
--------------------------------------------------------------------------------
/ROADMAP.md:
--------------------------------------------------------------------------------
1 | This project doesn't have a concrete road map. It's in the experimental stage
2 | right now. This `md` is just a list of problems whose solutions haven't been
3 | implemented or even figured out.
4 |
5 | For a few of these, I haven't decided whether they are problems Strawberry
6 | should be solving. In keeping with the theme of simplicity, there are ways
7 | around the problems, but they might feel convoluted.
8 |
9 | Ultimately this framework should feel intuitive and simple even if it is at the
10 | cost of not being able to do _everything_.
11 |
12 | **Terminology**:
13 |
14 | - Reactive Data Object (RDO): the object received when `sb.init` is called, when
15 | props of this object are updated, the UI updates.
16 |
17 | **List**
18 |
19 | - [ ] [Setting `sb-*` props for Strawberry inserted elements](#setting-sb--props-for-strawberry-inserted-elements)
20 | - [ ] [Directives for Strawberry Created Elements](#directives-for-strawberry-created-elements)
21 | - [ ] [Logic Encapsulation in Templates](#logic-encapsulation-in-templates)
22 | - [ ] [Interactive Elements in Templates](#interactive-elements-in-templates)
23 | - [ ] [Animating `sb-if`](#animating-sb-if)
24 | - [x] [Two-way Binding](#skip-two-way-binding) (SKIP)
25 | - [x] [Nested Components](#done-nested-components)
26 | - [x] [Defer Directives](#done-defer-ui-updates)
27 |
28 | # Setting `sb-*` props for Strawberry inserted elements
29 |
30 | **Problem** if I have a list of `a` elements which is added by strawberry
31 |
32 | ```html
33 |
34 |
35 |
38 | ```
39 |
40 | there is no way to set the `href` attribute.
41 |
42 | A **Solution** to this is to have a directive that sets attributes. This along
43 | with the nested components is a solution.
44 |
45 | ```html
46 |
47 |
48 |
49 |
52 | ```
53 |
54 | # Directives for Strawberry Created Elements
55 |
56 | **Problem** is when an element is created and inserted by strawberry, there is
57 | no way to init the properties of that element.
58 |
59 | This is more of a enhancement than an issue, should strawberry even do this.
60 |
61 | # Logic Encapsulation in Templates
62 |
63 | **Problem** is that scripts inside templates run in the global context. And if
64 | the template is external, they don't run.
65 |
66 | This means that templates can't have logic ascribed to them.
67 |
68 | # Interactive Elements in Templates
69 |
70 | **Problem** is that templates can have multiple interactive elements, inputs,
71 | buttons, etc. But accessing these elements requires traversing the Shadow DOM.
72 |
73 | # Animating `sb-if`
74 |
75 | **Problem** is that when `sb-if` causes a elements to be removed it's done using
76 | `el.replaceWith` which is not animatable.
77 |
78 | # `[DONE]` Defer UI updates
79 |
80 | **Problem** is that currently when an RDO prop is set in a regular `script` tag
81 |
82 | ```html
83 |
87 | ```
88 |
89 | only the elements before the script with the apt `sb-mark` are updated.
90 | Downstream elements are not updated.
91 |
92 | **Desired behavior** is that all elements are updated. Irrespective of the
93 | where the script is loaded.
94 |
95 | A **solution** is that when RDO props are set inside the `head` tag, the updates
96 | are deferred until the ready state changes to `"interactive"`. This happens only
97 | after the DOM has been parsed but before all assets have been fetched.
98 |
99 | # `[DONE]` Nested Components
100 |
101 | [PR #9](https://github.com/18alantom/strawberry/pull/9)
102 |
103 | **Problem** is that currently `sb-mark` on plain elements don't support nesting.
104 | For instance say I have a nested list:
105 |
106 | ```javascript
107 | data.list = [
108 | [1, 2],
109 | ['a', 'b', 'c'],
110 | ];
111 | ```
112 |
113 | Where I want the outer list items to be rendered in a `ul` and the inner ones
114 | in an `li`.
115 |
116 | ```html
117 |
118 |
119 |
1
120 |
2
121 |
122 |
123 |
a
124 |
b
125 |
c
126 |
127 |
128 | ```
129 |
130 | if the number of items in the outer list or inner list were fixed, it is
131 | possible to create templates with digit slot names:
132 |
133 | ```html
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | ```
146 |
147 | or just by using `sb-child`:
148 |
149 | ```html
150 |
151 |
152 |
153 | ```
154 |
155 | But for nested lists with a varying number of items it is not possible without
156 | using JavaScript. This is without even considering the nesting depth.
157 |
158 | A **solution** is to allow `sb-mark` items to have children that define the
159 | shape of the child:
160 |
161 | ```html
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 | ```
170 |
171 | This has the added advantage that the markup can be filled with placeholder data
172 | until the actual data loads. And to indicate that these are `sb-child` elements,
173 | they can be marked like so:
174 |
175 | ```html
176 |
177 |
178 |
loading...
179 |
180 |
181 | ```
182 |
183 | _Note: this prevents `"#"` from being used as a valid RDO prop name._
184 |
185 | # `[SKIP]` Two-way Binding
186 |
187 | **Problem** is `sb-mark` can't be used on input elements to change their
188 | value when the RDO prop changes, or vice versa.
189 |
190 | **Solution** is writing a new directive for this:
191 |
192 | ```javascript
193 | const data = sb.init({
194 | directives: {
195 | bind({ el, value, parent, prop }) {
196 | el.value = value;
197 | el.oninput ??= (e) => {
198 | parent[prop] = e.target.value;
199 | };
200 | },
201 | },
202 | });
203 | ```
204 |
205 | This is trivial, but the question is
206 |
207 | 1. Should this be in strawberry?
208 | 2. Should this be incorporated into `sb-mark` when element is an input element?
209 |
210 | Probably not considering, two way binding can be:
211 |
212 | - lazy: i.e. using a `change` listener
213 | - delayed: assignment takes place only after a time
214 |
215 | So, instead of inserting the batteries—in the spirit of simplicity—this probably won't be added in.
216 |
--------------------------------------------------------------------------------
/dist.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This file runs on yarn build. It converts index.ts to
4 | # minified javascript sb.min.js and adds the copyright
5 | # header file.
6 | #
7 | # Finally it prints the normal and gzipped sizes of the file.
8 |
9 | rm -rf dist
10 | mkdir dist
11 |
12 | version=$(cat package.json | grep '"version"' | cut -d'"' -f4)
13 | file_path="dist/sb.min.js"
14 | file_header="/* Strawberry $version
15 | * Copyright (c) 2023-present, Alan Tom (18alantom)
16 | * MIT License
17 | * This is a generated file. Do not edit.*/"
18 |
19 | echo "$file_header" >> "$file_path"
20 | node_modules/.bin/esbuild ./index.ts --bundle --minify --format=iife --global-name=sb >> "$file_path"
21 |
22 | size=$(wc -c < $file_path)
23 | gzsize=$(gzip -c $file_path | wc -c)
24 |
25 | kb=$(echo "scale=3; $size / 1024" | bc)
26 | gzkb=$(echo "scale=3; $gzsize / 1024" | bc)
27 |
28 | echo "dist/sb.min.js is ${kb}KB and gzipped ${gzkb}KB"
29 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Docs
2 |
3 | Strawberry is a simple frontend framework that gives you reactivity and
4 | composability.
5 |
6 | Here's the documentation index:
7 |
8 | 1. [Installation](./installation.md): explains how to pull Strawberry code into your web project.
9 | 2. [Getting Started](./getting_started.md): describes a simple example with code walk through.
10 | 3. [Reactivity](./reactivity/README.md): explains what is reactivity in Strawberry.
11 | 1. [Reactive Values](./reactivity/reactive_values.md): explains keys and values of the reactive object.
12 | 2. [Mark (`sb-mark`)](./reactivity/mark.md): explains how to mark an element to update along with data.
13 | 3. [Conditionals (`sb-if`, `sb-ifnot`)](./reactivity/conditionals.md): explains how to render or hide an element when data changes to truthy or falsy.
14 | 4. [Computed](./reactivity/computed.md): explains how to define reactive values that depend on other reactive values.
15 | 5. [Directives](./reactivity/directives.md): explains how to extend Strawberry with custom directives.
16 | 4. Composability (to be added)
17 | 5. [API](./api.md): lists all of Strawberry's defined directives and methods.
18 |
19 | If you want to get a quick round up of Strawberry check the
20 | [Getting Started](./getting_started.md) page. The remaining pages dwell deeper
21 | into individual topics and will be more clear after you have familiarized yourself
22 | with the basics.
23 |
--------------------------------------------------------------------------------
/docs/api.md:
--------------------------------------------------------------------------------
1 | # Strawberry API
2 |
3 | This page lists the available strawberry directives and exported methods.
4 |
5 | 1. **Directives**: set on elements ``
6 | 1. [`sb-mark`](#sb-mark): mark element as reactive.
7 | 2. [`sb-if`](#sb-if): render element if data is truthy.
8 | 3. [`sb-ifnot`](#sb-ifnot): render element if data is falsy.
9 | 2. **Methods**: called from the global `sb` object.
10 | 1. [`init`](#init): initialize strawberry.
11 | 2. [`directive`](#directive): register a custom directive.
12 | 3. [`watch`](#watch): watch data for changes.
13 | 4. [`unwatch`](#unwatch): stop watching data for changes.
14 | 5. [`register`](#register): register custom components.
15 | 6. [`load`](#load): load components from external files.
16 | 7. [`prefix`](#prefix): change prefix `"sb"` to a custom value.
17 |
18 | ## Directives
19 |
20 | Note this section is mentioned only completeness. for a more detailed
21 | information on the items in this section check out the documentation on
22 | [reactivity](./reactivity/README.md).
23 |
24 | ### `sb-mark`
25 |
26 | [Detailed documentation](./reactivity/mark.md)
27 |
28 | Used to mark an element with a key which will allow the element to be updated
29 | when the respective data changes.
30 |
31 | ```html
32 |
...
33 |
36 | ```
37 |
38 | ### `sb-if`
39 |
40 | [Detailed documentation](./reactivity/conditionals.md)
41 |
42 | Used to render an element when the respective data value is truthy.
43 |
44 | ```html
45 |
Hello, World!
46 |
49 | ```
50 |
51 | ### `sb-ifnot`
52 |
53 | [Detailed documentation](./reactivity/conditionals.md)
54 |
55 | Used to render an element when the respective data value is falsy.
56 |
57 | ```html
58 |
Hello, World!
59 |
62 | ```
63 |
64 | ## Methods
65 |
66 | If strawberry has been loaded correctly then all the methods mentioned in this
67 | section should be available on the global `sb` object.
68 |
69 | ### `init`
70 |
71 | ```typescript
72 | function init(): ReactiveObject;
73 | ```
74 |
75 | > **Info**
76 | >
77 | > `ReactiveObject` is not a specific type, it is an object that looks like a
78 | > regular JavaScript object but has reactive properties. For details check the
79 | > [Reactive Values](./reactivity/reactive_values.md) page.
80 |
81 | Used to initialize strawberry. Calling it does the following things:
82 |
83 | - Returns a reactive object which is used to store all [reactive data](./reactivity/README.md) in a Strawberry app.
84 | - Registers defined components.
85 |
86 | ```html
87 |
88 |
92 | ```
93 |
94 | When `sb.init` is called all templates elements with a name attribute are
95 | registered. Strawberry checks for component templates once again after the
96 | document is done loading, so it's alright to call `sb.init` in the ``
97 | element of a document.
98 |
99 | > **Info**
100 | >
101 | > Calling `sb.init` will always return the same reactive object so there is no
102 | > point in calling it multiple times. If you want to register components after
103 | > loading you should instead use `sb.register` or `sb.load`.
104 |
105 | ### `directive`
106 |
107 | [Detailed documentation](./reactivity/directives.md)
108 |
109 | ```typescript
110 | function directive(
111 | name: string,
112 | cb: Directive,
113 | isParametric: value = false
114 | ): void;
115 |
116 | type Directive = (params: {
117 | el: Element; // The element to which the directive has been applied.
118 | value: unknown; // The updated value.
119 | key: string; // Period '.' delimited key that points to the value in the global data object.
120 | isDelete: boolean; // Whether the value was deleted `delete data.prop`.
121 | parent: Prefixed