diff --git a/ui/packages/consul-ui/app/components/state-chart/README.mdx b/ui/packages/consul-ui/app/components/state-chart/README.mdx
index eb3a3fa1bc..a5bfc65787 100644
--- a/ui/packages/consul-ui/app/components/state-chart/README.mdx
+++ b/ui/packages/consul-ui/app/components/state-chart/README.mdx
@@ -3,6 +3,8 @@ class: ember
---
# StateChart
+**This component is deprecated and is currently undergoing an interface change in **
+
```hbs
+
+```
+
+`` is a renderless component that eases rendering of different states
+from within templates using XState State Machine and Statechart objects.
+
+**Please note**: This component is currently a gradual replacement for
+StateChart, which has a less ergonmic interface. Guard and Action component are
+currently omitted due to a preference to use entries to define those instead of
+components (which is WIP)
+
+### Arguments
+
+| Argument/Attribute | Type | Default | Description |
+| --- | --- | --- | --- |
+| `chart` | `object` | | An xstate statechart/state machine object |
+| `initial` | `String` | The initial value of the state chart itself | The initial state of the machine/chart (defaults to whatever is defined on the object itself) |
+
+The component currently yields 1 contextual components:
+
+- ``: Used for rendering matching certain states ([also see State Component](../state/README.mdx))
+
+and 2 further objects:
+
+- `fsm.dispatch`: An action to dispatch an xstate event
+- `fsm.state`: The state object itself for usage in the `state-matches` helper
+
+### Example
+
+```hbs
+
+
+ Currently Idle
+
+
+ Currently Loading
+
+
+ Idle and loading
+
+
+
+```
+
+### See
+
+- [Component Source Code](./index.js)
+- [Template Source Code](./index.hbs)
+
+---
diff --git a/ui/packages/consul-ui/app/components/state-machine/index.hbs b/ui/packages/consul-ui/app/components/state-machine/index.hbs
new file mode 100644
index 0000000000..82e792e669
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/state-machine/index.hbs
@@ -0,0 +1,7 @@
+{{yield
+ (hash
+ State=(component 'state' state=this.state)
+ dispatch=(action 'dispatch')
+ state=this.state
+ )
+}}
diff --git a/ui/packages/consul-ui/app/components/state-machine/index.js b/ui/packages/consul-ui/app/components/state-machine/index.js
new file mode 100644
index 0000000000..97507fb0ed
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/state-machine/index.js
@@ -0,0 +1,4 @@
+import Component from '../state-chart/index';
+
+export default Component.extend({});
+
diff --git a/ui/packages/consul-ui/app/components/state/README.mdx b/ui/packages/consul-ui/app/components/state/README.mdx
index 492dfee175..506c2b7363 100644
--- a/ui/packages/consul-ui/app/components/state/README.mdx
+++ b/ui/packages/consul-ui/app/components/state/README.mdx
@@ -1,6 +1,3 @@
----
-class: ember
----
# State
`Currently Idle`
diff --git a/ui/packages/consul-ui/app/components/state/index.hbs b/ui/packages/consul-ui/app/components/state/index.hbs
index a848649944..e717334e1c 100644
--- a/ui/packages/consul-ui/app/components/state/index.hbs
+++ b/ui/packages/consul-ui/app/components/state/index.hbs
@@ -1,3 +1,5 @@
-{{#if rendering}}
+{{did-insert this.attributeChanged @state @matches @notMatches}}
+{{did-update this.attributeChanged @state @matches @notMatches}}
+{{#if render}}
{{yield}}
{{/if}}
\ No newline at end of file
diff --git a/ui/packages/consul-ui/app/components/state/index.js b/ui/packages/consul-ui/app/components/state/index.js
index 3a77166183..3742bbe74c 100644
--- a/ui/packages/consul-ui/app/components/state/index.js
+++ b/ui/packages/consul-ui/app/components/state/index.js
@@ -1,20 +1,20 @@
-import Component from '@ember/component';
-import { set } from '@ember/object';
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { action } from '@ember/object';
import { inject as service } from '@ember/service';
-export default Component.extend({
- service: service('state'),
- tagName: '',
- didReceiveAttrs: function() {
- if (typeof this.state === 'undefined') {
+export default class State extends Component {
+ @service('state') state;
+
+ @tracked render = false;
+
+ @action
+ attributeChanged([state, matches, notMatches]) {
+ if (typeof state === 'undefined') {
return;
}
- let match = true;
- if (typeof this.matches !== 'undefined') {
- match = this.service.matches(this.state, this.matches);
- } else if (typeof this.notMatches !== 'undefined') {
- match = !this.service.matches(this.state, this.notMatches);
- }
- set(this, 'rendering', match);
- },
-});
+ this.render = typeof matches !== 'undefined' ?
+ this.state.matches(state, matches) :
+ !this.state.matches(state, notMatches);
+ }
+}
diff --git a/ui/packages/consul-ui/app/helpers/require.js b/ui/packages/consul-ui/app/helpers/require.js
index 1a8d9950dc..59f3606586 100644
--- a/ui/packages/consul-ui/app/helpers/require.js
+++ b/ui/packages/consul-ui/app/helpers/require.js
@@ -1,27 +1,11 @@
import { helper } from '@ember/component/helper';
+import require from 'require';
import { css } from '@lit/reactive-element';
-
import resolve from 'consul-ui/utils/path/resolve';
-import panel from 'consul-ui/components/panel/index.css';
-import distributionMeter from 'consul-ui/components/distribution-meter/index.css';
-import distributionMeterMeter from 'consul-ui/components/distribution-meter/meter/index.css';
-import distributionMeterMeterElement from 'consul-ui/components/distribution-meter/meter/element';
-import visuallyHidden from 'consul-ui/styles/base/decoration/visually-hidden.css';
-import baseKeyframes from 'consul-ui/styles/base/icons/base-keyframes.css';
-import chevronDown from 'consul-ui/styles/base/icons/icons/chevron-down/index.css';
-
-const fs = {
- ['/components/panel/index.css']: panel,
- ['/components/distribution-meter/index.css']: distributionMeter,
- ['/components/distribution-meter/meter/index.css']: distributionMeterMeter,
- ['/components/distribution-meter/meter/element']: distributionMeterMeterElement,
- ['/styles/base/decoration/visually-hidden.css']: visuallyHidden,
- ['/styles/base/icons/base-keyframes.css']: baseKeyframes,
- ['/styles/base/icons/icons/chevron-down/index.css']: chevronDown
-};
+const appName = 'consul-ui';
const container = new Map();
@@ -29,17 +13,27 @@ const container = new Map();
// we get the advantage of laziness here, i.e. we only call css as and when we
// need to
export default helper(([path = ''], { from }) => {
- const fullPath = resolve(from, path);
+ const fullPath = resolve(`${appName}${from}`, path);
+
+ let module;
+ if(require.has(fullPath)) {
+ module = require(fullPath).default;
+ } else {
+ throw new Error(`Unable to resolve '${fullPath}' does the file exist?`)
+ }
+
switch(true) {
case fullPath.endsWith('.css'):
- return fs[fullPath](css)
+ return module(css);
+ case fullPath.endsWith('.xstate'):
+ return module;
default: {
if(container.has(fullPath)) {
return container.get(fullPath);
}
- const module = fs[fullPath](HTMLElement);
- container.set(fullPath, module);
- return module;
+ const component = module(HTMLElement);
+ container.set(fullPath, component);
+ return component;
}
}
});