Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
8009a5e
Bump dependencies
rkusan00 Aug 28, 2025
1cf72ff
Add callElementAction support and handling
rkusan00 Feb 23, 2026
e93e510
Update example
rkusan00 Feb 26, 2026
ae8df33
Migrate to Vuetify 4 and bump all dependencies
rkusan00 Feb 26, 2026
9f8dcf8
Cleanup styles
rkusan00 Feb 27, 2026
667fa71
Cleanup dependencies
rkusan00 Feb 27, 2026
429792c
Add isEmpty prop
rkusan00 Feb 27, 2026
c77c411
Add question autosave support
rkusan00 Mar 9, 2026
1bbb8ee
Pass init and isEmpty to edit runtime
rkusan00 Mar 9, 2026
578e7e6
Expand documentation with question autosave and fix typos
rkusan00 Mar 9, 2026
8045988
Bump dependencies
rkusan00 Mar 9, 2026
c9bf29f
Address issues
rkusan00 Mar 10, 2026
61cc357
Make server actions self-contained by removing element dependency
rkusan00 Mar 11, 2026
7c6960b
Rename actions to rpc/procedures
rkusan00 Mar 12, 2026
993806c
Lint fixes
rkusan00 Mar 12, 2026
9974785
Bump major versions
rkusan00 Mar 12, 2026
deb29bb
Update readme
rkusan00 Mar 12, 2026
7917ad8
Lint fixes
rkusan00 Mar 12, 2026
ce94fd5
Bump dependencies
rkusan00 Mar 13, 2026
3d6533f
Fix wrong export
rkusan00 Mar 13, 2026
61c80a0
Migrate to vite 8
rkusan00 Mar 13, 2026
c35135d
Fix readme
rkusan00 Mar 13, 2026
98bede0
Cleanup
rkusan00 Mar 13, 2026
dbc9b8e
Update storage api
rkusan00 Mar 16, 2026
19e784a
Cleanup
rkusan00 Mar 16, 2026
a51c07e
Provide TailorAssetInput global component
rkusan00 Mar 17, 2026
9c41ac3
Consolidate into single AssetInput component
rkusan00 Mar 17, 2026
c211a18
Add vuetify types
rkusan00 Mar 17, 2026
eb40c92
Add global components docs
rkusan00 Mar 17, 2026
459d478
Update docs
rkusan00 Mar 17, 2026
336c183
Release beta
rkusan00 Mar 17, 2026
83792c4
Revert resolveAssets helper
rkusan00 Mar 18, 2026
b468f49
Add element placeholder as global component
rkusan00 Mar 18, 2026
4ddc2f3
Cleanup
rkusan00 Mar 18, 2026
4e84170
Add missing pom methods
rkusan00 Mar 18, 2026
c6d12d0
Introduce e2e tests api helpers
rkusan00 Mar 18, 2026
40a5c6a
Expand elementclient
rkusan00 Mar 18, 2026
aa15deb
Add test to example
rkusan00 Mar 18, 2026
ea8c7ab
Bump beta version
rkusan00 Mar 18, 2026
f6295c0
Add private packages flags
rkusan00 Mar 18, 2026
f436db4
Cleanup
rkusan00 Mar 19, 2026
ebf6049
Add button aria label
rkusan00 Mar 20, 2026
b8e4e3b
A11y tweaks
rkusan00 Mar 20, 2026
b959a35
Lighouse fixes
rkusan00 Mar 20, 2026
d9d75df
Auto-wrap Questions
rkusan00 Mar 25, 2026
340b364
Cleanup
rkusan00 Mar 25, 2026
5c0596a
Auto wrap question on display
rkusan00 Mar 25, 2026
b87f72c
Expose question form poms
rkusan00 Mar 25, 2026
efabeca
Update documentation
rkusan00 Mar 25, 2026
ef21d1f
Migrate to tsdown
rkusan00 Apr 1, 2026
76a4737
Enable isolatedDeclarations
rkusan00 Apr 1, 2026
2ba40bc
Update changelog
rkusan00 Apr 1, 2026
973cc01
Fix changelog
rkusan00 Apr 1, 2026
1463b14
Bump dependencies
rkusan00 Apr 1, 2026
632a85a
Cleanup
rkusan00 Apr 2, 2026
1ec1e00
Add engine
rkusan00 Apr 2, 2026
0226540
Cleanup
rkusan00 Apr 3, 2026
91b3405
Bump dependencies
rkusan00 Apr 3, 2026
6b43f20
Cleanup
rkusan00 Apr 7, 2026
8c8d63a
Bump minors
rkusan00 Apr 7, 2026
0a4ff15
Migrate ky
rkusan00 Apr 7, 2026
3851aca
Cleanup
rkusan00 Apr 7, 2026
f072862
Cleanup dependencies
rkusan00 Apr 7, 2026
6b318fc
Cleanup
rkusan00 Apr 7, 2026
8e2d85c
Swap uuid
rkusan00 Apr 7, 2026
78b13f0
Cleanup
rkusan00 Apr 7, 2026
4886edb
Implement new file input component
rkusan00 Apr 7, 2026
ad256c4
Cleanup
rkusan00 Apr 7, 2026
52d0aa5
Bump version
rkusan00 Apr 7, 2026
6432879
Add isEmpty guard
rkusan00 Apr 7, 2026
bc6be8f
Add theme testing support
rkusan00 Apr 8, 2026
1308061
Tweak linking experience
rkusan00 Apr 8, 2026
bb67ed0
Update changelog
rkusan00 Apr 8, 2026
7319c62
Cleanup
rkusan00 Apr 8, 2026
f744934
Bump dependencies
rkusan00 Apr 8, 2026
6d85e54
Bump version
rkusan00 Apr 8, 2026
2cae53d
Update changelog
rkusan00 Apr 8, 2026
8634718
Pass init config to init fn
rkusan00 Apr 9, 2026
1074afe
Cleanup
rkusan00 Apr 9, 2026
3bcc738
Fix versions and cleanup changelogs
rkusan00 Apr 9, 2026
8101c43
Bump version
rkusan00 Apr 9, 2026
e918a4b
Cleanup
rkusan00 Apr 9, 2026
3864f18
Lint fixes
rkusan00 Apr 9, 2026
9083670
Bump dependencies
rkusan00 Apr 9, 2026
a0f421e
Move counter to examples dir
rkusan00 Apr 9, 2026
ccaebe7
Add question example element
rkusan00 Apr 9, 2026
54665d4
Make counter default
rkusan00 Apr 9, 2026
0f830d3
Add dev script
rkusan00 Apr 9, 2026
31303e1
Fix devcontainer config
rkusan00 Apr 9, 2026
16499d6
Update changesets config
rkusan00 Apr 9, 2026
556650f
Fix container image
rkusan00 Apr 9, 2026
3e10a0e
Cleanup
rkusan00 Apr 10, 2026
7580ca8
Fix boot
rkusan00 Apr 10, 2026
2c26d9a
Fix tce boot
rkusan00 Apr 10, 2026
d06364d
add open browser to devcontainer setup
rkusan00 Apr 10, 2026
451fab8
Cleanup
rkusan00 Apr 10, 2026
95ccc34
Bump dependencies
rkusan00 Apr 10, 2026
cbdcc01
Replace deprecated vuetify theme setters
rkusan00 Apr 10, 2026
84cece1
Bump beta
rkusan00 Apr 10, 2026
3e24cad
Fix storage upload signature
rkusan00 Apr 11, 2026
7a353a5
Bump beta
rkusan00 Apr 11, 2026
659eb8a
Fix theme dialog warnings
rkusan00 Apr 14, 2026
4f92eca
Fix focus
rkusan00 Apr 14, 2026
6bffd14
Fix error messages
rkusan00 Apr 15, 2026
af63537
Bump dependencies
rkusan00 Apr 15, 2026
80ae841
Cleanup file input
rkusan00 Apr 15, 2026
8c2de41
Bump beta
rkusan00 Apr 15, 2026
e0f602c
Cleanup
rkusan00 Apr 15, 2026
28b4f48
Update types
rkusan00 Apr 15, 2026
50c98db
Add download to FileInput
rkusan00 Apr 16, 2026
95d227d
Tweak interfaces
rkusan00 Apr 17, 2026
49fc24e
Bump dependencies
rkusan00 Apr 17, 2026
d1f38a2
Bump versions
rkusan00 Apr 17, 2026
9817ecf
Bump devcontainers
rkusan00 Apr 17, 2026
2538d0f
Tweak file input and add pom
rkusan00 Apr 17, 2026
1cfc41b
Bump beta
rkusan00 Apr 17, 2026
e122ff6
Cleanup changelog
rkusan00 Apr 17, 2026
fbaf9c2
Tweak edit panel pom
rkusan00 Apr 17, 2026
b9c0eff
Bump versions
rkusan00 Apr 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,16 @@
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
"ignore": [
"tce-counter",
"tce-counter-manifest",
"tce-counter-edit",
"tce-counter-display",
"tce-counter-server",
"tce-question",
"tce-question-manifest",
"tce-question-edit",
"tce-question-display",
"tce-question-server"
]
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Tailor - Content Element",
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm",
"name": "Tailor XT — Counter example",
"image": "mcr.microsoft.com/devcontainers/typescript-node:4-24-trixie",
"features": {
"ghcr.io/devcontainers-extra/features/pnpm:2": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
Expand All @@ -24,8 +24,8 @@
"onAutoForward": "silent"
}
},
"postCreateCommand": "pnpm install --frozen-lockfile && pnpm build",
"postAttachCommand": "/bin/bash .devcontainer/setup.sh && pnpm dev",
"postCreateCommand": "pnpm install --frozen-lockfile && pnpm build && pnpm -C examples/counter run build",
"postAttachCommand": "/bin/bash .devcontainer/setup.sh && pnpm -C examples/counter run dev",
"customizations": {
"vscode": {
"settings": {
Expand Down
62 changes: 62 additions & 0 deletions .devcontainer/question/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "Tailor XT — Question example",
"image": "mcr.microsoft.com/devcontainers/typescript-node:4-24-trixie",
"features": {
"ghcr.io/devcontainers-extra/features/pnpm:2": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"forwardPorts": [8080, 8010, 8020, 8030],
"portsAttributes": {
"8080": {
"label": "Content Element Kit preview",
"onAutoForward": "notify"
},
"8010": {
"label": "Edit runtime",
"onAutoForward": "silent"
},
"8020": {
"label": "Display runtime",
"onAutoForward": "silent"
},
"8030": {
"label": "Server runtime",
"onAutoForward": "silent"
}
},
"postCreateCommand": "pnpm install --frozen-lockfile && pnpm build && pnpm -C examples/question run build",
"postAttachCommand": "/bin/bash .devcontainer/setup.sh && pnpm -C examples/question run dev",
"customizations": {
"vscode": {
"settings": {
"editor.formatOnSave": true,
"eslint.enable": true,
"prettier.requireConfig": true,
"files.exclude": {
"**/.pnpm": true,
"**/node_modules": true
},
"workbench.colorTheme": "One Dark Pro",
"oneDarkPro.editorFontLigatures": true,
"oneDarkPro.bold": true,
"oneDarkPro.italic": true,
"editor.fontSize": 20,
"editor.fontFamily": "'Dank Mono', 'Fira Code', monospace",
"editor.fontLigatures": true
},
"extensions": [
"akamud.vscode-theme-onedark",
"zhuangtongfa.Material-theme",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"mikestead.dotenv",
"sainoba.px-to-rem",
"stylelint.vscode-stylelint",
"zhuangtongfa.material-theme",
"EditorConfig.EditorConfig",
"Vue.volar",
"GitHub.copilot"
]
}
}
}
File renamed without changes.
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# Changelog

### v2.0.0 2026-04-17

#### Breaking Changes
- Migrated to Vuetify 4 (MD3 typography classes, updated component API,
theme configuration). All content element packages using Vuetify components
need to be updated.
- Question auto-wrap — `QuestionCard` and `QuestionContainer` are now applied
automatically by the runtime. Elements must remove manual wrapping.
- Build toolchain migrated from tsup to tsdown.
- `isolatedDeclarations` enabled — all exported symbols require explicit type
annotations.
- `StorageApi.upload` now takes a native `File` instead of a `FormData`
payload. The `UploadFormData` and `UploadFormFieldname` type exports have
been removed.
- `mocks` manifest type extracted to a standalone `ElementMocks` interface;
`DisplayContext` relocated to `element-interfaces`.
- TypeScript 6, Vite 8.

#### Features
- Typed hook signatures (`ElementHook`, `BeforeDisplayHook`,
`OnUserInteractionHook`, `ProcedureHandler`).
- `ServerModule` and `HookMap` types for typed server package default exports.
- `AiConfig` type (replaces inline `OpenAISchema` casting pattern).
- RPC procedures — custom server-side methods callable from Edit components
via the injected `$rpc` function.
- `isEmpty` manifest function for required element validation.
- `showFeedback` manifest field to control question feedback section visibility.
- Question autosave support.
- `mocks.referencesData` manifest field for custom mock linked element data.
- CEK theme testing — ThemeDialog in edit and display runtimes.
- `TailorAssetInput` global component (consolidated from separate upload
components).
- `TailorElementPlaceholder` global component.
- `TailorFileInput` global component for file uploads in the edit runtime.
- New `question` example element alongside `counter`; examples relocated to
`examples/` and `counter` is now the default boot target.
- Expanded E2E testing utilities (`@tailor-cms/cek-e2e`) with API helpers and
additional page object models.
- Accessibility improvements.

#### Other
- `moduleResolution: "bundler"` across all tsconfigs.
- Bumped all dependencies to the latest versions.

### v1.0.0 2024-02-07

#### Changes
Expand Down
48 changes: 46 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
# `xt` Tailor extensions kit
# Content Element Kit

Development framework for building [Tailor CMS](https://github.com/tailor-cms/author) content elements in isolation.

Provides a 4-runtime architecture for authoring, displaying, and testing
content elements:

- **Edit** — Authoring runtime emulating the Tailor CMS environment
- **Display** — End-user runtime emulating the delivery (LMS) environment
- **Server** — Server runtime for hooks, procedures, and storage
- **Preview** — Inspector UI combining all runtimes

## Packages

| Package | Description |
|---|---|
| `@tailor-cms/cek-common` | Shared types, API client, WebSocket utils |
| `@tailor-cms/tce-edit-runtime` | Edit runtime |
| `@tailor-cms/tce-display-runtime` | Display runtime |
| `@tailor-cms/tce-server-runtime` | Server runtime |
| `@tailor-cms/tce-preview-runtime` | Preview inspector UI |
| `@tailor-cms/tce-boot` | Dev orchestrator |
| `@tailor-cms/cek-e2e` | E2E testing utilities |
| `@tailor-cms/eslint-config` | Shared ESLint config |

## Documentation

See the [documentation site](https://tailor-cms.github.io/xt/) for
installation, usage, and API reference.

## Quick start

```bash
pnpm install
pnpm dev
```

`pnpm dev` opens an interactive picker for the bundled [examples/](examples/),
then boots the selection across all four runtimes — accessible from the
Preview inspector (default `localhost:8080`).

To skip the picker, pass the example name directly:

```bash
pnpm dev counter
```

Provides base runtime for developing Tailor teaching elements.
2 changes: 1 addition & 1 deletion docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default defineConfig({
{ text: "Introduction", link: "/introduction" },
{ text: "Installation", link: "/installation" },
{ text: "Example", link: "/example" },
{ text: "Environment variables", link: "/enviroment-variables" },
{ text: "Environment variables", link: "/environment-variables" },
],
},
{
Expand Down
6 changes: 3 additions & 3 deletions docs/ai.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ AI configuration is defined by the following:
Here is an example configuration for a counter element:

```ts
import { OpenAISchema } from '@tailor-cms/cek-common';
import type { AiConfig } from '@tailor-cms/cek-common';

export const ai = {
export const ai: AiConfig = {
Schema: {
type: 'json_schema',
name: 'ce_counter',
Expand All @@ -36,7 +36,7 @@ export const ai = {
required: ['count', 'description'],
additionalProperties: false,
},
} as OpenAISchema,
},
getPrompt: () => `
Generate counter content element as an object with the following
properties: { "description": "", "count": 0 }.
Expand Down
78 changes: 65 additions & 13 deletions docs/display-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Display package is the subpackage located under `packages/display` exposing
`Vue 3` component needed for the Content Element `end-user` rendering. The
component recieves authored values as props. Here is an example of a Display
component receives authored values as props. Here is an example of a Display
component for the Simple Counter Content Element from the Edit package section:

\
Expand Down Expand Up @@ -36,16 +36,15 @@ is a reserved property).

In the example above, we use the `userState` prop to display the last time the
user has seen the element. In order to achieve that, we need a way to report
user activity from the `Display` component. The specification implements
`interaction` event, which can be used to report user activity to the `end-user`
system. Emitting `interaction` event will result in `onUserInteraction` server
hook being called, where one can implement user state handling and other
interaction-specific handling. For more details on this, visit section
on [user-state hooks](./server-package#user-state-hooks).
user activity from the `Display` component.

\
Here is a simple example of element submitting interaction event for backend to
process:
### Non-question elements

Non-question Display components emit the `interaction` event to report user
activity to the end-user system. Emitting `interaction` triggers the
`onUserInteraction` server hook, where you can implement user state handling
and other interaction-specific logic. For more details, visit the section
on [user-state hooks](./server-package#user-state-hooks).

\
`Display.vue`
Expand All @@ -61,15 +60,68 @@ process:
import { Element } from 'tce-manifest';

const props = defineProps<{ element: Element; userState: any }>();
const emit = defineEmits(['interaction']);
const emit = defineEmits<{ interaction: [data: any] }>();

const submit = () => emit('interaction', { myInteractionData: 'example' });
</script>
```

:::tip State persistance and user event handling
### Question elements

Question Display components emit `user-input` instead of `interaction`. The
framework auto-wraps question Display components inside a `QuestionForm`
which provides the standard question layout (prompt, hint, submit/retry
controls, feedback). The element only provides the answer-specific UI.

The `QuestionForm` captures `user-input` events from the inner component,
validates the form on submit, and emits `interaction` to the runtime — which
triggers the `onUserInteraction` server hook.

\
`Display.vue`
```vue
<template>
<div>
<VRadioGroup v-model="selectedAnswer">
<VRadio
v-for="(answer, i) in element.data.answers"
:key="i"
:label="answer"
:value="i"
:disabled="userState?.isSubmitted"
/>
</VRadioGroup>
</div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import { Element } from 'tce-manifest';

const props = defineProps<{ element: Element; userState: any }>();
const emit = defineEmits<{ 'user-input': [data: any] }>();

const selectedAnswer = ref(props.userState?.response ?? null);

watch(selectedAnswer, (val) => {
if (val !== null) emit('user-input', { response: val });
});
</script>
```

Note: The element does **not** include a submit button — the `QuestionForm`
provides submit/retry controls and manages the submission lifecycle.

### Event flow summary

| Element Type | Component Emits | Container | Runtime Receives |
|-------------|----------------|-----------|-----------------|
| Non-question | `interaction` | — | `interaction` → `onUserInteraction` hook |
| Question | `user-input` | QuestionForm → `interaction` | `interaction` → `onUserInteraction` hook |

:::tip State persistence and user event handling
It is up to the `end-user`/`target system` to define mechanisms for end-user
state persistance or any other additional behaviour.
state persistence or any other additional behaviour.
:::

## Composite Elements
Expand Down
Loading
Loading