diff --git a/DistributionTool.exe b/DistributionTool.exe
old mode 100644
new mode 100755
diff --git a/Makefile b/Makefile
index cd74ca6..9c2869e 100644
--- a/Makefile
+++ b/Makefile
@@ -35,23 +35,36 @@ endif
.DEFAULT_GOAL := build
test:
- cd $(SRCDIR)/code && go run $(GOFLAGS) main.go handlers.go pi.go vmix.go -port 12345 -pluginUUID 213 -registerEvent test -info "{\"application\":{\"language\":\"en\",\"platform\":\"mac\",\"version\":\"4.1.0\"},\"plugin\":{\"version\":\"1.1\"},\"devicePixelRatio\":2,\"devices\":[{\"id\":\"55F16B35884A859CCE4FFA1FC8D3DE5B\",\"name\":\"Device Name\",\"size\":{\"columns\":5,\"rows\":3},\"type\":0},{\"id\":\"B8F04425B95855CF417199BCB97CD2BB\",\"name\":\"Another Device\",\"size\":{\"columns\":3,\"rows\":2},\"type\":1}]}"
+ cd $(SRCDIR)/code && go run $(GOFLAGS) cmd/main.go -port 12345 -pluginUUID 213 -registerEvent test -info "{\"application\":{\"language\":\"en\",\"platform\":\"mac\",\"version\":\"4.1.0\"},\"plugin\":{\"version\":\"1.1\"},\"devicePixelRatio\":2,\"devices\":[{\"id\":\"55F16B35884A859CCE4FFA1FC8D3DE5B\",\"name\":\"Device Name\",\"size\":{\"columns\":5,\"rows\":3},\"type\":0},{\"id\":\"B8F04425B95855CF417199BCB97CD2BB\",\"name\":\"Another Device\",\"size\":{\"columns\":3,\"rows\":2},\"type\":1}]}"
vet:
cd $(SRCDIR)/code && go vet
-prepare:
+setup-pi:
+ cd $(PIDIR) && npm install
+
+setup-server:
+ cd $(SRCDIR)/code && go mod tidy
+
+setup: setup-pi setup-server
+
+prepare:
@$(MKDIR) $(BUILDDIR)
@$(RM) $(BUILDDIR)/*
+ @$(RM) ./$(RELEASEDIR)/*
-build: prepare
+build-pi:
+ cd $(SRCDIR)/pi && npm run build
+
+build-server:
cd $(SRCDIR)/code/cmd && GOOS=windows GOARCH=amd64 go build -o $(BUILDDIR)/vmix_go.exe .
cd $(SRCDIR)/code/cmd && GOOS=darwin GOARCH=amd64 go build -o $(BUILDDIR)/vmix_go .
- $(CP) $(PIDIR) $(BUILDDIR)/inspector
+
+build: prepare build-pi build-server
+ $(CP) $(PIDIR)/dist $(BUILDDIR)/inspector
$(CP) $(SRCDIR)/manifest.json $(BUILDDIR)
$(CP) $(SRCDIR)/images $(BUILDDIR)
distribute: build
- @$(RM) ./$(RELEASEDIR)/*
@$(MKDIR) $(RELEASEDIR)
$(DISTRIBUTION_TOOL) -b -i $(APPNAME) -o $(RELEASEDIR)
\ No newline at end of file
diff --git a/Source/code/action/action.go b/Source/code/action/action.go
new file mode 100644
index 0000000..ec2f365
--- /dev/null
+++ b/Source/code/action/action.go
@@ -0,0 +1,14 @@
+// Package action provides the action interface and its implementations.
+//
+// Each Action interface does not belong to a specific "button".
+// Instead, it is a usecase(logics) that can own any button.
+// Action interface owns each StreamDeck context internally.
+
+package action
+
+import "context"
+
+type Action interface {
+ Tally(ctx context.Context, host string, input int) error
+ Activator(ctx context.Context) error // TODO...
+}
diff --git a/Source/code/action/preview.go b/Source/code/action/preview.go
new file mode 100644
index 0000000..685585a
--- /dev/null
+++ b/Source/code/action/preview.go
@@ -0,0 +1,196 @@
+package action
+
+import (
+ "context"
+ "errors"
+ "slices"
+
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/adapter/adapters"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/logger/loggers"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/setting"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/solver"
+ vmixtcp "github.com/FlowingSPDG/vmix-go/tcp"
+
+ "github.com/FlowingSPDG/streamdeck"
+ sdcontext "github.com/FlowingSPDG/streamdeck/context"
+ "golang.org/x/sync/errgroup"
+ "golang.org/x/xerrors"
+)
+
+const PreviewActionUUID = "dev.flowingspdg.vmix.preview"
+
+type PreviewAction interface {
+ Appear(ctx context.Context, setting *setting.PreviewSetting) error
+ Disappear(ctx context.Context, setting *setting.PreviewSetting) error
+ UpdateSetting(ctx context.Context, setting *setting.PreviewSetting) error
+ Execute(ctx context.Context) error
+ Tally(ctx context.Context, host string, tally *vmixtcp.TallyResponse) error
+}
+
+type previewAction struct {
+ logger loggers.Logger
+
+ // adapters
+ streamDeckAdapter adapters.StreamDeckContextAdapter
+ vmixAdapter adapters.VMixAdapter
+
+ // solver
+ solver solver.Solver
+
+ // internal
+ store setting.SettingStore[setting.PreviewSetting]
+}
+
+func NewPreviewAction(
+ logger loggers.Logger,
+ streamDeckAdapter adapters.StreamDeckContextAdapter,
+ vmixAdapter adapters.VMixAdapter,
+ solver solver.Solver,
+ store setting.SettingStore[setting.PreviewSetting],
+) PreviewAction {
+ return &previewAction{
+ logger: logger,
+ streamDeckAdapter: streamDeckAdapter,
+ vmixAdapter: vmixAdapter,
+ solver: solver,
+ store: store,
+ }
+}
+
+func (p *previewAction) Appear(ctx context.Context, setting *setting.PreviewSetting) error {
+ if err := p.logger.LogMessage(ctx, "preview action appeared"); err != nil {
+ return xerrors.Errorf("failed to log message: %w", err)
+ }
+
+ p.storeNewVmix(ctx, setting)
+
+ return nil
+}
+
+func (p *previewAction) Disappear(ctx context.Context, setting *setting.PreviewSetting) error {
+ if err := p.logger.LogMessage(ctx, "preview action disappeared"); err != nil {
+ return xerrors.Errorf("failed to log message: %w", err)
+ }
+
+ ctxStr := sdcontext.Context(ctx)
+ if ctxStr == "" {
+ return errors.New("failed to get context")
+ }
+
+ p.store.Delete(ctxStr)
+ p.vmixAdapter.RemoveVMix(ctx)
+
+ return nil
+}
+
+func (p *previewAction) UpdateSetting(ctx context.Context, setting *setting.PreviewSetting) error {
+ if err := p.logger.LogMessage(ctx, "preview action received updated setting: %v", setting); err != nil {
+ return xerrors.Errorf("failed to log message: %w", err)
+ }
+
+ // 既存の設定と新しい設定を比較して、設定が変更されていれば更新する
+ ctxStr := sdcontext.Context(ctx)
+ if ctxStr == "" {
+ return errors.New("failed to get context")
+ }
+ oldSetting, _ := p.store.Load(ctxStr)
+ if oldSetting.Host == setting.Host && oldSetting.Input == setting.Input {
+ return nil
+ }
+
+ // ここで古いvMixのインスタンスを削除する
+ p.vmixAdapter.RemoveVMix(ctx)
+ p.storeNewVmix(ctx, setting)
+
+ return nil
+}
+
+func (p *previewAction) Execute(ctx context.Context) error {
+ if err := p.logger.LogMessage(ctx, "preview action executing"); err != nil {
+ return xerrors.Errorf("failed to log message: %w", err)
+ }
+
+ ctxStr := sdcontext.Context(ctx)
+ if ctxStr == "" {
+ return errors.New("failed to get context")
+ }
+
+ s, ok := p.store.Load(ctxStr)
+ if !ok {
+ return errors.New("failed to get settings for context " + ctxStr)
+ }
+
+ if err := p.vmixAdapter.PreviewInput(s.Host, s.Input); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (p *previewAction) Tally(ctx context.Context, host string, tally *vmixtcp.TallyResponse) error {
+ if err := p.logger.LogMessage(ctx, "preview action received tally signal"); err != nil {
+ return xerrors.Errorf("failed to log message: %w", err)
+ }
+
+ contextStrs, ok := p.solver.SolveByHost(host)
+ if !ok {
+ return xerrors.Errorf("unknown host detected: %s", host)
+ }
+
+ contextStrs = slices.DeleteFunc(contextStrs, func(s string) bool {
+ setting, ok := p.store.Load(s)
+ if !ok {
+ return false
+ }
+ return !setting.Tally || setting.Host != host || setting.Input == 0 || setting.Input > len(tally.Tally)
+ })
+
+ eg := errgroup.Group{}
+ for _, contextStr := range contextStrs {
+ eg.Go(func() error {
+ if err := p.logger.LogMessage(ctx, "Applying tally for context %s", contextStr); err != nil {
+ return xerrors.Errorf("failed to log message: %w", err)
+ }
+
+ cctx := sdcontext.WithContext(ctx, contextStr)
+
+ // PIの設定を読み出す
+ s, ok := p.store.Load(contextStr)
+ if !ok {
+ return xerrors.Errorf("failed to get settings for context %s", contextStr)
+ }
+
+ // 設定情報をもとに、Tallyをセットする
+ target := s.Input - 1
+ if tally.Tally[target] == vmixtcp.Preview {
+ if err := p.streamDeckAdapter.SetPreviewColor(cctx, streamdeck.HardwareAndSoftware); err != nil {
+ return xerrors.Errorf("failed to set tally: %w", err)
+ }
+ return nil
+ }
+
+ if err := p.logger.LogMessage(ctx, "Applying Preview tally for context %s", contextStr); err != nil {
+ return xerrors.Errorf("failed to log message: %w", err)
+ }
+ if err := p.streamDeckAdapter.SetInactiveColor(cctx, streamdeck.HardwareAndSoftware); err != nil {
+ return xerrors.Errorf("failed to set tally: %w", err)
+ }
+ return nil
+ })
+ }
+ if err := eg.Wait(); err != nil {
+ return xerrors.Errorf("failed to apply tally: %w", err)
+ }
+ return nil
+}
+
+func (p *previewAction) storeNewVmix(ctx context.Context, setting *setting.PreviewSetting) error {
+ ctxStr := sdcontext.Context(ctx)
+ if ctxStr == "" {
+ return errors.New("failed to get context")
+ }
+
+ p.store.Store(ctxStr, setting)
+ p.vmixAdapter.AddVMix(ctx, setting.Host)
+ return nil
+}
diff --git a/Source/code/adapter/adapters/adapters.go b/Source/code/adapter/adapters/adapters.go
new file mode 100644
index 0000000..5139ab2
--- /dev/null
+++ b/Source/code/adapter/adapters/adapters.go
@@ -0,0 +1,32 @@
+package adapters
+
+import (
+ "context"
+
+ "github.com/FlowingSPDG/streamdeck"
+ vmixtcp "github.com/FlowingSPDG/vmix-go/tcp"
+)
+
+type StreamDeckContextAdapter interface {
+ // TALLY
+ SetInactiveColor(ctx context.Context, target streamdeck.Target) error
+ SetPreviewColor(ctx context.Context, target streamdeck.Target) error
+ SetProgramColor(ctx context.Context, target streamdeck.Target) error
+
+ SendInputs(ctx context.Context, inputs map[string]Input) error
+}
+
+type Input struct {
+ Number int `json:"number"`
+ Name string `json:"name"`
+ Key string `json:"key"`
+}
+
+type VMixAdapter interface {
+ AddVMix(ctx context.Context, destination string)
+ RemoveVMix(ctx context.Context)
+ PreviewInput(destination string, input int) error
+ OnTally(f func(ctx context.Context, host string, tally *vmixtcp.TallyResponse) error)
+ // OnVersion(f func(ctx context.Context, host string, version *vmixtcp.VersionResponse) error)
+ OnXML(f func(ctx context.Context, host string, xml *vmixtcp.XMLResponse) error)
+}
diff --git a/Source/code/stdvmix.go b/Source/code/adapter/streamdeck.go
similarity index 73%
rename from Source/code/stdvmix.go
rename to Source/code/adapter/streamdeck.go
index 27e14dd..37cef48 100644
--- a/Source/code/stdvmix.go
+++ b/Source/code/adapter/streamdeck.go
@@ -1,211 +1,43 @@
-package stdvmix
+package adapter
import (
"context"
- "fmt"
- "reflect"
- "sync"
- "time"
"github.com/FlowingSPDG/streamdeck"
- sdcontext "github.com/FlowingSPDG/streamdeck/context"
-)
-
-const (
- // AppName Streamdeck plugin app name
- AppName = "dev.flowingspdg.vmix.sdPlugin"
-
- // ActionFunction SendFunction action Name
- ActionFunction = "dev.flowingspdg.vmix.function"
- // ActionPreview Preview input action Name
- ActionPreview = "dev.flowingspdg.vmix.preview"
-
- // ActionProgram Take input action Name
- ActionProgram = "dev.flowingspdg.vmix.program"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/adapter/adapters"
)
const (
- // tally color
tallyInactive string = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAC6HpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHja7Zddch0pDIXfWUWWgCSExHJofqqyg1l+DnTf9r12ZpLUzMtUXagGLOiD0KfGdhh/fZ/hGwqVzCGpeS45R5RUUuGKgcezlN1STLvdJT3m6NUe7gmGSdDL+aPVa32FXT9euHWOV3vwa4b9EqJbeBdZO69xf3YSdj7tlC6hMs5BLm7Prh6XULsWbleu5+l493HDi8EQpa7YSJiHkMTdptMDWQ9JRZ/QshSso21R8XCaLjEE5OV4jz7G5wC9BPkxCp+jf48+BZ/rZZdPscxXjDD46QTpJ7vc2/DzxnJ7xK8TJg+pr0Ges/uc4zxdTRkRzVdG7WDTQwYLD4Rc9msZ1fAoxrZrQfVYYwPyHls8UBsVYlCZgRJ1qjRp7L5Rg4uJBxt65gZQy+ZiXLjJ4pRWpckmRbo4YDUeQQRmvn2hvW/Z+zVy7NwJS5kgRnjlb2v4p8k/qWHOtkJE0e9YwS9eeQ03FrnVYhWA0Ly46Q7wo17441P+IFVBUHeYHQes8TglDqWP3JLNWbBO0Z+fEAXrlwBChL0VziDtE8VMopQpGrMRIY4OQBWesyQ+QIBUucNJTiK4j4yd1954x2ivZeXMy4y7CSBUshjYFKmAlZIifyw5cqiqaFLVrKYetGjNklPWnLPldclVE0umls3MrVh18eTq2c3di9fCRXAHasnFipdSauVQsVGFVsX6CsvBhxzp0CMfdvhRjtqQPi01bblZ81Za7dyl45rouVv3XnodFAZuipGGjjxs+CijTuTalJmmzjxt+iyz3tQuql/qH1CjixpvUmud3dRgDWYPCVrXiS5mIMaJQNwWASQ0L2bRKSVe5BazWBgfhTKc1MUmdFrEgDANYp10s/sg91vcgvpvceNfkQsL3X9BLgDdV24/odbX77m2iZ1f4YppFHx903plD3hiRPNv+7fQW+gt9BZ6C72F3kL/fyGZ+OMB/xSGH33UnVw3YM8qAAAAZ3pUWHRSYXcgcHJvZmlsZSB0eXBlIGlwdGMAAHjaPUxBDoAwDLr3FT5hg6rrc5bOgzcP/j/iYoSUNoVg53WnLRO+GZvDw0dx8QdQs4C7zk6waCqGtkvBmG7KPVjFzlVFfKOhwPdiswf3FBdySWckggAAAYRpQ0NQSUNDIHByb2ZpbGUAAHicfZE9SMNAHMVf00pFKh3sIKKQoTpZEBXpqFUoQoVQK7TqYHLpFzRpSFJcHAXXgoMfi1UHF2ddHVwFQfADxM3NSdFFSvxfWmgR48FxP97de9y9A4RGhWlWYALQdNtMJxNiNrcqBl8RwAgExBGWmWXMSVIKnuPrHj6+3sV4lve5P0e/mrcY4BOJZ5lh2sQbxDObtsF5nzjCSrJKfE48btIFiR+5rrT4jXPRZYFnRsxMep44QiwWu1jpYlYyNeJp4qiq6ZQvZFusct7irFVqrH1P/sJQXl9Z5jrNYSSxiCVIEKGghjIqsBGjVSfFQpr2Ex7+IdcvkUshVxmMHAuoQoPs+sH/4He3VmFqspUUSgA9L47zMQoEd4Fm3XG+jx2neQL4n4ErveOvNoD4J+n1jhY9AsLbwMV1R1P2gMsdYPDJkE3Zlfw0hUIBeD+jb8oBA7dA31qrt/Y+Th+ADHWVugEODoGxImWve7y7t7u3f8+0+/sBda5yqHjnlIUAAA9ZaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA0LjQuMC1FeGl2MiI+CiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICB4bWxuczppcHRjRXh0PSJodHRwOi8vaXB0Yy5vcmcvc3RkL0lwdGM0eG1wRXh0LzIwMDgtMDItMjkvIgogICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgeG1sbnM6cGx1cz0iaHR0cDovL25zLnVzZXBsdXMub3JnL2xkZi94bXAvMS4wLyIKICAgIHhtbG5zOkdJTVA9Imh0dHA6Ly93d3cuZ2ltcC5vcmcveG1wLyIKICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgeG1wTU06RG9jdW1lbnRJRD0iZ2ltcDpkb2NpZDpnaW1wOjViY2U0YWU3LTI5OTMtNDI0ZS04MDgwLWEzMzJjMTc2OGM4OCIKICAgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5Y2JiMTk3MS1mMmFiLTRlMDQtYjdmNy1hODAxZmRiMGE0NzMiCiAgIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZWM4Nzc0OC04MmVjLTRiOWYtOTg1MC1lNmJlNDY0MTJiZTYiCiAgIEdJTVA6QVBJPSIyLjAiCiAgIEdJTVA6UGxhdGZvcm09Ik1hYyBPUyIKICAgR0lNUDpUaW1lU3RhbXA9IjE2MTk2NjUxMTA5ODcyNjQiCiAgIEdJTVA6VmVyc2lvbj0iMi4xMC4xNCIKICAgZGM6Rm9ybWF0PSJpbWFnZS9wbmciCiAgIHhtcDpDcmVhdG9yVG9vbD0iR0lNUCAyLjEwIj4KICAgPGlwdGNFeHQ6TG9jYXRpb25DcmVhdGVkPgogICAgPHJkZjpCYWcvPgogICA8L2lwdGNFeHQ6TG9jYXRpb25DcmVhdGVkPgogICA8aXB0Y0V4dDpMb2NhdGlvblNob3duPgogICAgPHJkZjpCYWcvPgogICA8L2lwdGNFeHQ6TG9jYXRpb25TaG93bj4KICAgPGlwdGNFeHQ6QXJ0d29ya09yT2JqZWN0PgogICAgPHJkZjpCYWcvPgogICA8L2lwdGNFeHQ6QXJ0d29ya09yT2JqZWN0PgogICA8aXB0Y0V4dDpSZWdpc3RyeUlkPgogICAgPHJkZjpCYWcvPgogICA8L2lwdGNFeHQ6UmVnaXN0cnlJZD4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0OmNoYW5nZWQ9Ii8iCiAgICAgIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MDNhZmM1ZDMtZGI4ZC00NjA4LTliN2UtNDQwNzFmMzY3YWUxIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJHaW1wIDIuMTAgKE1hYyBPUykiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMDQtMjlUMTE6NTg6MzArMDk6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogICA8cGx1czpJbWFnZVN1cHBsaWVyPgogICAgPHJkZjpTZXEvPgogICA8L3BsdXM6SW1hZ2VTdXBwbGllcj4KICAgPHBsdXM6SW1hZ2VDcmVhdG9yPgogICAgPHJkZjpTZXEvPgogICA8L3BsdXM6SW1hZ2VDcmVhdG9yPgogICA8cGx1czpDb3B5cmlnaHRPd25lcj4KICAgIDxyZGY6U2VxLz4KICAgPC9wbHVzOkNvcHlyaWdodE93bmVyPgogICA8cGx1czpMaWNlbnNvcj4KICAgIDxyZGY6U2VxLz4KICAgPC9wbHVzOkxpY2Vuc29yPgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+7MRfwQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+UEHQI6HgGMPmcAAABySURBVHja7dAxEQAwCASwUuUY/zsUsDMkElJJ+rH6CgQJEiRIkCBBghAkSJAgQYIECUKQIEGCBAkSJAhBggQJEiRIkCBBCBIkSJAgQYIEIUiQIEGCBAkShCBBggQJEiRIkCAECRIkSJAgQYIQJEiQoCsG1+IEBwGJzGQAAAAASUVORK5CYII="
tallyPreview string = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAC83pUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHja7ZdftuMmDMbfWUWXgCSExHIwf86ZHXT5/cCOb3LvTDsz7UMfAseGCPwh9JNJEsaf32b4A4VKTiGpeS45R5RUUuGKjsezlH2nmPZ9l/QYo1d7uAcYJkEr50er1/wKu348cOscr/bg1wj7JUS38C6yVl79/uwk7HzaKV1CZZydXNyeXT0uoXZN3K5c19P27u2GF4MhSl2xkDAPIYn7nk4PZF0kFW3CnaVgHm2LigU0JH6JISAv23u0MT4H6CXIj174HP279yn4XC+7fIplvmKEzncHSD/Z5V6GnxeW2yN+HTB9SH0N8pzd5xzn7mrKiGi+MmoHmx4ymHgg5LIfy6iGS9G3XQuqxxobkPfY4oHaqBCDygyUqFOlSWO3jRpcTDzY0DI3gFo2F+PCTRantCpNNinSxcGv8QgiMPPtC+11y16vkWPlTpjKBDHCIz+s4e8Gf6WGOdsKEUW/YwW/eOU13Fjk1h2zAITmxU13gB/1wh+f8gepCoK6w+zYYI3HKXEofeSWbM6CeYr2fIUoWL8EECKsrXAGaZ8oZhKlTNGYjQhxdACq8Jwl8QECpModTnISyRyMndfaeMZoz2XlzMuMswkgVLIY2BSpgJWSIn8sOXKoqmhS1aymHrRozZJT1pyz5XXIVRNLppbNzK1YdfHk6tnN3YvXwkVwBmrJxYqXUmrlULFQhVbF/ArLwYcc6dAjH3b4UY7akD4tNW25WfNWWu3cpeOY6Llb9156HRQGToqRho48bPgoo07k2pSZps48bfoss97ULqpf6i9Qo4sab1Jrnt3UYA1mDwlax4kuZiDGiUDcFgEkNC9m0SklXuQWs1gYL4UynNTFJnRaxIAwDWKddLP7IPdT3IL6T3HjfyIXFrr/glwAuq/cvkOtr++5tomdb+GKaRS8fT1X9hr4mEjfiZd0fcS322+24d8KvIXeQm+ht9Bb6C30Fvp/CAl+QOCPbPgLErueUnLkblgAAABmelRYdFJhdyBwcm9maWxlIHR5cGUgaXB0YwAAeNo9SkEOgDAMuvcVPmGFarfnLJsHbx78fySLEVIgBbvuZ9i2EIexBqLFLCH+AHwUMBU7waJzTHlIwbbaofaki527MWXOqsH3YtoL9uAXbmjIu/EAAAGEaUNDUElDQyBwcm9maWxlAAB4nH2RPUjDQBzFX9NKRSod7CCikKE6WRAV6ahVKEKFUCu06mBy6Rc0aUhSXBwF14KDH4tVBxdnXR1cBUHwA8TNzUnRRUr8X1poEePBcT/e3XvcvQOERoVpVmAC0HTbTCcTYja3KgZfEcAIBMQRlpllzElSCp7j6x4+vt7FeJb3uT9Hv5q3GOATiWeZYdrEG8Qzm7bBeZ84wkqySnxOPG7SBYkfua60+I1z0WWBZ0bMTHqeOEIsFrtY6WJWMjXiaeKoqumUL2RbrHLe4qxVaqx9T/7CUF5fWeY6zWEksYglSBChoIYyKrARo1UnxUKa9hMe/iHXL5FLIVcZjBwLqEKD7PrB/+B3t1ZharKVFEoAPS+O8zEKBHeBZt1xvo8dp3kC+J+BK73jrzaA+Cfp9Y4WPQLC28DFdUdT9oDLHWDwyZBN2ZX8NIVCAXg/o2/KAQO3QN9aq7f2Pk4fgAx1lboBDg6BsSJlr3u8u7e7t3/PtPv7AXWucqh455SFAAAPWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAtRXhpdjIiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6aXB0Y0V4dD0iaHR0cDovL2lwdGMub3JnL3N0ZC9JcHRjNHhtcEV4dC8yMDA4LTAyLTI5LyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgIHhtbG5zOnBsdXM9Imh0dHA6Ly9ucy51c2VwbHVzLm9yZy9sZGYveG1wLzEuMC8iCiAgICB4bWxuczpHSU1QPSJodHRwOi8vd3d3LmdpbXAub3JnL3htcC8iCiAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgIHhtcE1NOkRvY3VtZW50SUQ9ImdpbXA6ZG9jaWQ6Z2ltcDo3ZjI1NjAzOC0xOTkwLTQ5Y2MtOTVlMi1jNzI3NDBjYzYxNTAiCiAgIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDk4N2VkNDktMTZhMC00NjA4LWE4NzItYzNiN2ZmMmY0ZDlhIgogICB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6YjIwOWVhZGMtZjFmNC00MDQxLWE5NzMtYTkwZGFhYTdhOTUzIgogICBHSU1QOkFQST0iMi4wIgogICBHSU1QOlBsYXRmb3JtPSJNYWMgT1MiCiAgIEdJTVA6VGltZVN0YW1wPSIxNjE5NjY1MDQxMDUyOTAxIgogICBHSU1QOlZlcnNpb249IjIuMTAuMTQiCiAgIGRjOkZvcm1hdD0iaW1hZ2UvcG5nIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJTVAgMi4xMCI+CiAgIDxpcHRjRXh0OkxvY2F0aW9uQ3JlYXRlZD4KICAgIDxyZGY6QmFnLz4KICAgPC9pcHRjRXh0OkxvY2F0aW9uQ3JlYXRlZD4KICAgPGlwdGNFeHQ6TG9jYXRpb25TaG93bj4KICAgIDxyZGY6QmFnLz4KICAgPC9pcHRjRXh0OkxvY2F0aW9uU2hvd24+CiAgIDxpcHRjRXh0OkFydHdvcmtPck9iamVjdD4KICAgIDxyZGY6QmFnLz4KICAgPC9pcHRjRXh0OkFydHdvcmtPck9iamVjdD4KICAgPGlwdGNFeHQ6UmVnaXN0cnlJZD4KICAgIDxyZGY6QmFnLz4KICAgPC9pcHRjRXh0OlJlZ2lzdHJ5SWQ+CiAgIDx4bXBNTTpIaXN0b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InNhdmVkIgogICAgICBzdEV2dDpjaGFuZ2VkPSIvIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjdjNzkzZjA3LTViNjQtNDc0ZS04Mjk3LWYzMTFlOTczMDkwYyIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iR2ltcCAyLjEwIChNYWMgT1MpIgogICAgICBzdEV2dDp3aGVuPSIyMDIxLTA0LTI5VDExOjU3OjIxKzA5OjAwIi8+CiAgICA8L3JkZjpTZXE+CiAgIDwveG1wTU06SGlzdG9yeT4KICAgPHBsdXM6SW1hZ2VTdXBwbGllcj4KICAgIDxyZGY6U2VxLz4KICAgPC9wbHVzOkltYWdlU3VwcGxpZXI+CiAgIDxwbHVzOkltYWdlQ3JlYXRvcj4KICAgIDxyZGY6U2VxLz4KICAgPC9wbHVzOkltYWdlQ3JlYXRvcj4KICAgPHBsdXM6Q29weXJpZ2h0T3duZXI+CiAgICA8cmRmOlNlcS8+CiAgIDwvcGx1czpDb3B5cmlnaHRPd25lcj4KICAgPHBsdXM6TGljZW5zb3I+CiAgICA8cmRmOlNlcS8+CiAgIDwvcGx1czpMaWNlbnNvcj4KICA8L3JkZjpEZXNjcmlwdGlvbj4KIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/Plfb3jAAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQflBB0CORW9c7QsAAAAcElEQVR42u3QMQEAAAgDoGn/zprA3wMiUJlMOLUCQYIECRIkSJAgBAkSJEiQIEGCECRIkCBBggQJQpAgQYIECRIkSBCCBAkSJEiQIEEIEiRIkCBBggQhSJAgQYIECRIkCEGCBAkSJEiQIAQJEiToiwUf1QKOQh77lQAAAABJRU5ErkJggg=="
tallyProgram string = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV/TSkUqHewgopChOlkQFemoVShChVArtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APEzc1J0UVK/F9aaBHjwXE/3t173L0DhEaFaVZgAtB020wnE2I2tyoGXxHACATEEZaZZcxJUgqe4+sePr7exXiW97k/R7+atxjgE4lnmWHaxBvEM5u2wXmfOMJKskp8Tjxu0gWJH7mutPiNc9FlgWdGzEx6njhCLBa7WOliVjI14mniqKrplC9kW6xy3uKsVWqsfU/+wlBeX1nmOs1hJLGIJUgQoaCGMiqwEaNVJ8VCmvYTHv4h1y+RSyFXGYwcC6hCg+z6wf/gd7dWYWqylRRKAD0vjvMxCgR3gWbdcb6PHad5AvifgSu94682gPgn6fWOFj0CwtvAxXVHU/aAyx1g8MmQTdmV/DSFQgF4P6NvygEDt0DfWqu39j5OH4AMdZW6AQ4OgbEiZa97vLu3u7d/z7T7+wF1rnKoxhB+yAAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+UEHQI4IYXccdgAAABwSURBVHja7dAxAQAACAOgaf/OmsDfAyJQk0w4tQJBggQJEiRIkCAECRIkSJAgQYIQJEiQIEGCBAlCkCBBggQJEiRIEIIECRIkSJAgQQgSJEiQIEGCBCFIkCBBggQJEiQIQYIECRIkSJAgBAkSJOiLBSDUAo5LcSa/AAAAAElFTkSuQmCC"
)
-type input struct {
- Name string `json:"name"`
- Key string `json:"key"`
- Number int `json:"number"`
-}
-
-type StdVmix struct {
- c *streamdeck.Client
-
- sendFuncContexts sync.Map // map[string]SendFunctionPI
- previewContexts sync.Map // map[string]PreviewPI
- programContexts sync.Map // map[string]ProgramPI
+type streamDeckContextAdapter struct {
+ client *streamdeck.Client
}
-func NewStdVmix(ctx context.Context, params streamdeck.RegistrationParams) *StdVmix {
- client := streamdeck.NewClient(ctx, params)
- ret := &StdVmix{
- c: client,
- sendFuncContexts: sync.Map{},
- previewContexts: sync.Map{},
- programContexts: sync.Map{},
+func NewStreamDeckContextAdapter(client *streamdeck.Client) adapters.StreamDeckContextAdapter {
+ return &streamDeckContextAdapter{
+ client: client,
}
-
- actionFunc := client.Action(ActionFunction)
- actionFunc.RegisterHandler(streamdeck.WillAppear, ret.SendFuncWillAppearHandler)
- actionFunc.RegisterHandler(streamdeck.WillDisappear, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- ret.sendFuncContexts.Delete(event.Context)
- return nil
- })
- actionFunc.RegisterHandler(streamdeck.KeyDown, ret.SendFuncKeyDownHandler)
- actionFunc.RegisterHandler(streamdeck.DidReceiveSettings, ret.SendFuncDidReceiveSettingsHandler)
-
- actionPrev := client.Action(ActionPreview)
- actionPrev.RegisterHandler(streamdeck.WillAppear, ret.PreviewWillAppearHandler)
- actionPrev.RegisterHandler(streamdeck.WillDisappear, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- ret.previewContexts.Delete(event.Context)
- return nil
- })
- actionPrev.RegisterHandler(streamdeck.KeyDown, ret.PreviewKeyDownHandler)
- actionPrev.RegisterHandler(streamdeck.DidReceiveSettings, ret.PreviewDidReceiveSettingsHandler)
-
- actionProgram := client.Action(ActionProgram)
- actionProgram.RegisterHandler(streamdeck.WillAppear, ret.ProgramWillAppearHandler)
- actionProgram.RegisterHandler(streamdeck.WillDisappear, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- ret.programContexts.Delete(event.Context)
- return nil
- })
- actionProgram.RegisterHandler(streamdeck.KeyDown, ret.ProgramKeyDownHandler)
- actionProgram.RegisterHandler(streamdeck.DidReceiveSettings, ret.ProgramDidReceiveSettingsHandler)
-
- ret.c = client
-
- return ret
}
-// Update inputs Contextの数だけ更新が入るので負荷が高いかもしれない
-func (s *StdVmix) Update() {
- wg := sync.WaitGroup{}
- s.sendFuncContexts.Range(func(key, value any) bool {
- ctxStr := key.(string)
- val, ok := value.(SendFunctionPI)
- if !ok {
- msg := fmt.Sprintf("Failed to cast value for sendfunc. Actual:%s", reflect.TypeOf(value))
- s.c.LogMessage(msg)
- return true
- }
- wg.Add(1)
- defer wg.Done()
- go func(ctxStr string, pi SendFunctionPI) {
- ctx := context.Background()
- ctx = sdcontext.WithContext(ctx, ctxStr)
-
- // val を使ってinputを更新
- if err := pi.UpdateInputs(); err != nil {
- // アクセスに失敗したときのログがうるさいので、errorによってログに出すか分岐したい
- s.c.LogMessage("Failed to update inputs")
- return
- }
- s.c.SetSettings(ctx, val)
- }(ctxStr, val)
- return true
- })
-
- s.previewContexts.Range(func(key, value any) bool {
- ctxStr := key.(string)
- val, ok := value.(PreviewPI)
- if !ok {
- msg := fmt.Sprintf("Failed to cast value for preview. Actual:%s", reflect.TypeOf(value))
- s.c.LogMessage(msg)
- return true
- }
- wg.Add(1)
- defer wg.Done()
- go func(ctxStr string, pi PreviewPI) {
- ctx := context.Background()
- ctx = sdcontext.WithContext(ctx, ctxStr)
-
- // val を使ってinputを更新
- if err := pi.UpdateInputs(); err != nil {
- s.c.LogMessage("Failed to update inputs")
- return
- }
- s.c.SetSettings(ctx, pi)
-
- if !pi.Tally {
- return
- }
- prev, err := pi.UpdateTally()
- if err != nil {
- s.c.LogMessage("Failed to get tally for preview")
- return
- }
- if prev {
- s.c.SetImage(ctx, tallyPreview, streamdeck.HardwareAndSoftware)
- return
- }
- s.c.SetImage(ctx, tallyInactive, streamdeck.HardwareAndSoftware)
- }(ctxStr, val)
- return true
- })
-
- s.programContexts.Range(func(key, value any) bool {
- ctxStr := key.(string)
- val, ok := value.(ProgramPI)
- if !ok {
- msg := fmt.Sprintf("Failed to cast value for program. Actual:%s", reflect.TypeOf(value))
- s.c.LogMessage(msg)
- return true
- }
- wg.Add(1)
- defer wg.Done()
- go func(ctxStr string, pi ProgramPI) {
- ctx := context.Background()
- ctx = sdcontext.WithContext(ctx, ctxStr)
-
- // pi を使ってinputを更新
- if err := pi.UpdateInputs(); err != nil {
- s.c.LogMessage("Failed to update inputs")
- return
- }
- s.c.SetSettings(ctx, pi)
-
- if !pi.Tally {
- return
- }
- pgm, err := pi.UpdateTally()
- if err != nil {
- s.c.LogMessage("Failed to get tally for preview")
- return
- }
- if pgm {
- s.c.SetImage(ctx, tallyProgram, streamdeck.HardwareAndSoftware)
- return
- }
- s.c.SetImage(ctx, tallyInactive, streamdeck.HardwareAndSoftware)
- }(ctxStr, val)
- return true
- })
+func (s *streamDeckContextAdapter) SetInactiveColor(ctx context.Context, target streamdeck.Target) error {
+ return s.client.SetImage(ctx, tallyInactive, target)
+}
- wg.Wait()
- return
+func (s *streamDeckContextAdapter) SetPreviewColor(ctx context.Context, target streamdeck.Target) error {
+ return s.client.SetImage(ctx, tallyPreview, target)
+}
+func (s *streamDeckContextAdapter) SetProgramColor(ctx context.Context, target streamdeck.Target) error {
+ return s.client.SetImage(ctx, tallyProgram, target)
}
-func (s *StdVmix) Run(ctx context.Context) error {
- go func() {
- for {
- time.Sleep(time.Second / 5) // 0.2s
- select {
- case <-ctx.Done():
- return
- default:
- s.Update()
- }
- }
- }()
- return s.c.Run()
+func (s *streamDeckContextAdapter) SendInputs(ctx context.Context, inputs map[string]adapters.Input) error {
+ return s.client.SendToPropertyInspector(ctx, map[string]any{
+ "event": "inputs",
+ "inputs": inputs,
+ })
}
diff --git a/Source/code/adapter/vmix.go b/Source/code/adapter/vmix.go
new file mode 100644
index 0000000..16b862c
--- /dev/null
+++ b/Source/code/adapter/vmix.go
@@ -0,0 +1,172 @@
+package adapter
+
+import (
+ "context"
+ "time"
+
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/adapter/adapters"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/logger/loggers"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/solver"
+
+ sdcontext "github.com/FlowingSPDG/streamdeck/context"
+ vmixtcp "github.com/FlowingSPDG/vmix-go/tcp"
+ "github.com/puzpuzpuz/xsync/v3"
+ "golang.org/x/xerrors"
+)
+
+type vMixAdapter struct {
+ // callbacks
+ onTally func(ctx context.Context, host string, tally *vmixtcp.TallyResponse) error
+ // onVersion func(ctx context.Context, host string, version *vmixtcp.VersionResponse) error
+ onXML func(ctx context.Context, host string, xml *vmixtcp.XMLResponse) error
+
+ // logger
+ logger loggers.Logger
+
+ // solver
+ solver solver.Solver
+
+ // vMix instances
+ // TODO: solverへ共通化できるかも?
+ vs *xsync.MapOf[string, *vmixInstance]
+}
+
+type vmixInstance struct {
+ vmix vmixtcp.Vmix
+ ctx context.Context
+ cancel context.CancelFunc
+}
+
+func NewVMixAdapter(
+ logger loggers.Logger,
+ solver solver.Solver,
+) adapters.VMixAdapter {
+ return &vMixAdapter{
+ logger: logger,
+ solver: solver,
+ vs: xsync.NewMapOf[string, *vmixInstance](),
+ }
+}
+
+func (v *vMixAdapter) PreviewInput(destination string, input int) error {
+ panic("not implemented") // TODO: Implement
+}
+
+func (v *vMixAdapter) AddVMix(ctx context.Context, destination string) {
+ v.logger.LogMessage(ctx, "add vmix host: %s", destination)
+
+ ctxStr := sdcontext.Context(ctx)
+ if ctxStr == "" {
+ panic("context is not registered")
+ }
+
+ // 紐づけ登録をする
+ v.solver.AddHost(destination, ctxStr)
+
+ // canceler
+ cctx, cancel := context.WithCancel(context.Background())
+
+ // vMixのインスタンスを保持する
+ vmix := vmixtcp.New(destination)
+ v.vs.Store(destination, &vmixInstance{
+ vmix: vmix,
+ ctx: cctx,
+ cancel: cancel,
+ })
+ v.startRetry(cctx, destination)
+}
+
+func (v *vMixAdapter) RemoveVMix(ctx context.Context) {
+ ctxStr := sdcontext.Context(ctx)
+ removed := v.solver.RemoveContext(ctxStr)
+ if removed {
+ // vMixのインスタンスを削除する
+ vi, ok := v.vs.Load(ctxStr)
+ if ok {
+ panic("SOMETHING WENT WRONG!!")
+ }
+
+ vi.cancel()
+ v.vs.Delete(ctxStr)
+ }
+}
+
+func (v *vMixAdapter) startRetry(ctx context.Context, host string) {
+ v.logger.LogMessage(ctx, "start retry for %s", host)
+ go func() {
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case <-time.After(time.Second):
+ if err := v.retry(ctx, host); err != nil {
+ v.logger.LogMessage(ctx, "failed to retry: %v", err)
+ }
+ }
+ }
+ }()
+
+}
+
+func (v *vMixAdapter) retry(ctx context.Context, host string) error {
+ v.logger.LogMessage(ctx, "retrying for %s", host)
+
+ // vMixのインスタンスが削除されている場合、再接続処理を行わない
+ vi, ok := v.vs.Load(host)
+ if !ok {
+ v.logger.LogMessage(ctx, "destination %s is probably deleted. Abort!", host)
+
+ return nil
+ }
+
+ if vi.vmix.IsConnected() {
+ v.logger.LogMessage(ctx, "destination %s is already connected. Abort!", host)
+
+ return nil
+ }
+
+ v.logger.LogMessage(ctx, "Trying to connect destination %s ...", host)
+
+ // 1.接続処理を行う
+ if err := vi.vmix.Connect(vi.ctx, time.Second); err != nil {
+ return xerrors.Errorf("failed to connect to vMix: %w", err)
+ }
+ v.logger.LogMessage(ctx, "connected to vMix destination %s. Register callbacks...", host)
+
+ // 2: コールバックを登録する
+ vi.vmix.OnVersion(func(vr *vmixtcp.VersionResponse) {
+ // バージョン情報を受け取ったときの処理
+ v.logger.LogMessage(ctx, "VersionResponse: %v", vr)
+ if err := vi.vmix.Subscribe(vmixtcp.EventTally, ""); err != nil {
+ panic(err)
+ }
+ })
+ vi.vmix.OnTally(func(tr *vmixtcp.TallyResponse) {
+ // Tally情報を受け取ったときの処理
+ v.logger.LogMessage(ctx, "TallyResponse: %v", tr)
+ v.onTally(ctx, host, tr)
+ })
+ vi.vmix.OnXML(func(xr *vmixtcp.XMLResponse) {
+ // XML情報を受け取ったときの処理
+ v.logger.LogMessage(ctx, "XMLResponse: %v", xr)
+ v.onXML(ctx, host, xr)
+ })
+ // 追加でACTSにSUBSCRIBEする場合、設定項目からSUBSCRIBE対象を取得する
+
+ v.logger.LogMessage(ctx, "Registered callbacks %s", host)
+
+ // 3: 接続に成功したら、vMixの状態を監視する
+ if err := vi.vmix.Run(vi.ctx); err != nil {
+ return xerrors.Errorf("failed to run vMix: %w", err)
+ }
+
+ return nil
+}
+
+func (v *vMixAdapter) OnTally(f func(ctx context.Context, host string, tally *vmixtcp.TallyResponse) error) {
+ v.onTally = f
+}
+
+func (v *vMixAdapter) OnXML(f func(ctx context.Context, host string, xml *vmixtcp.XMLResponse) error) {
+ v.onXML = f
+}
diff --git a/Source/code/cmd/main.go b/Source/code/cmd/main.go
index f7fb6cb..8bf5e4d 100644
--- a/Source/code/cmd/main.go
+++ b/Source/code/cmd/main.go
@@ -2,39 +2,18 @@ package main
import (
"context"
- _ "embed"
- "io"
- "log"
- "os"
- "github.com/FlowingSPDG/streamdeck"
-
- stdvmix "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/action"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/di"
)
func main() {
- logfile, err := os.Create("./streamdeck-vmix-plugin.log")
- if err != nil {
- panic("cannnot open log:" + err.Error())
- }
- defer logfile.Close()
- log.SetOutput(io.MultiWriter(logfile, os.Stdout))
- log.SetFlags(log.Ldate | log.Ltime)
-
ctx := context.Background()
- log.Println("Starting...")
- if err := run(ctx); err != nil {
- panic(err)
- }
-}
-
-func run(ctx context.Context) error {
- params, err := streamdeck.ParseRegistrationParams(os.Args)
- if err != nil {
- return err
- }
- client := stdvmix.NewStdVmix(ctx, params)
+ streamDeckClient := di.InitializeStreamDeckClient(ctx)
+ previewActionController := di.InitializePreviewActionController(ctx, streamDeckClient)
+ previewAction := streamDeckClient.Action(action.PreviewActionUUID)
+ previewActionController.RegisterAction(previewAction)
- return client.Run(ctx)
+ streamDeckClient.Run(ctx)
}
diff --git a/Source/code/controller/controllers/controllers.go b/Source/code/controller/controllers/controllers.go
new file mode 100644
index 0000000..3acf9d7
--- /dev/null
+++ b/Source/code/controller/controllers/controllers.go
@@ -0,0 +1,24 @@
+package controllers
+
+import (
+ "context"
+
+ "github.com/FlowingSPDG/streamdeck"
+ vmixtcp "github.com/FlowingSPDG/vmix-go/tcp"
+)
+
+type PreviewActionController interface {
+ // register
+ RegisterAction(sdAction *streamdeck.Action)
+
+ // handlers
+ WillAppearHandler() streamdeck.EventHandler
+ WilDisappearHandler() streamdeck.EventHandler
+ KeyDownHandler() streamdeck.EventHandler
+ DidReceiveSettingsHandler() streamdeck.EventHandler
+}
+
+type VMixController interface {
+ OnTally(ctx context.Context, host string, tally *vmixtcp.TallyResponse) error
+ // OnXML(ctx context.Context, host string, xml *vmixtcp.XMLResponse) error
+}
diff --git a/Source/code/controller/preview.go b/Source/code/controller/preview.go
new file mode 100644
index 0000000..77469a5
--- /dev/null
+++ b/Source/code/controller/preview.go
@@ -0,0 +1,80 @@
+package controller
+
+import (
+ "context"
+ "encoding/json"
+
+ "github.com/FlowingSPDG/streamdeck"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/action"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/controller/controllers"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/setting"
+
+ "golang.org/x/xerrors"
+)
+
+type previewActionController struct {
+ // actions
+ previewAction action.PreviewAction
+}
+
+func NewPreviewActionController(previewAction action.PreviewAction) controllers.PreviewActionController {
+ return &previewActionController{
+ previewAction: previewAction,
+ }
+}
+
+func (s *previewActionController) RegisterAction(sdAction *streamdeck.Action) {
+ sdAction.RegisterHandler(streamdeck.WillAppear, s.WillAppearHandler())
+ sdAction.RegisterHandler(streamdeck.WillDisappear, s.WilDisappearHandler())
+ sdAction.RegisterHandler(streamdeck.KeyDown, s.KeyDownHandler())
+ sdAction.RegisterHandler(streamdeck.DidReceiveSettings, s.DidReceiveSettingsHandler())
+}
+
+func (s *previewActionController) WillAppearHandler() streamdeck.EventHandler {
+ return func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
+ p := streamdeck.WillAppearPayload[setting.PreviewSetting]{}
+ if err := json.Unmarshal(event.Payload, &p); err != nil {
+ return xerrors.Errorf("failed to unmarshal setting from payload: %w", err)
+ }
+ if err := s.previewAction.Appear(ctx, &p.Settings); err != nil {
+ return xerrors.Errorf("failed to appear: %w", err)
+ }
+ return nil
+ }
+}
+
+func (s *previewActionController) WilDisappearHandler() streamdeck.EventHandler {
+ return func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
+ p := streamdeck.WillDisappearPayload[setting.PreviewSetting]{}
+ if err := json.Unmarshal(event.Payload, &p); err != nil {
+ return xerrors.Errorf("failed to unmarshal setting from payload: %w", err)
+ }
+ if err := s.previewAction.Disappear(ctx, &p.Settings); err != nil {
+ return xerrors.Errorf("failed to disappear: %w", err)
+ }
+ return nil
+ }
+}
+
+func (s *previewActionController) KeyDownHandler() streamdeck.EventHandler {
+ return func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
+ if err := s.previewAction.Execute(ctx); err != nil {
+ return xerrors.Errorf("failed to execute: %w", err)
+ }
+ return nil
+ }
+}
+
+func (s *previewActionController) DidReceiveSettingsHandler() streamdeck.EventHandler {
+ return func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
+ p := streamdeck.DidReceiveSettingsPayload[setting.PreviewSetting]{}
+ if err := json.Unmarshal(event.Payload, &p); err != nil {
+ return xerrors.Errorf("failed to unmarshal setting from payload: %w", err)
+ }
+
+ if err := s.previewAction.UpdateSetting(ctx, &p.Settings); err != nil {
+ return xerrors.Errorf("failed to update setting: %w", err)
+ }
+ return nil
+ }
+}
diff --git a/Source/code/controller/vmix.go b/Source/code/controller/vmix.go
new file mode 100644
index 0000000..09fb7a9
--- /dev/null
+++ b/Source/code/controller/vmix.go
@@ -0,0 +1,81 @@
+package controller
+
+import (
+ "context"
+ "strconv"
+
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/action"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/adapter/adapters"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/controller/controllers"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/solver"
+
+ sdcontext "github.com/FlowingSPDG/streamdeck/context"
+ vmixtcp "github.com/FlowingSPDG/vmix-go/tcp"
+ "golang.org/x/sync/errgroup"
+ "golang.org/x/xerrors"
+)
+
+type vmixController struct {
+ // adapters
+ vMixAdapter adapters.VMixAdapter
+ streamDeckAdapter adapters.StreamDeckContextAdapter
+
+ // internal
+ solver solver.Solver
+
+ // actions
+ previewAction action.PreviewAction
+}
+
+func NewVMixController(
+ vmixAdapter adapters.VMixAdapter,
+ streamDeckAdapter adapters.StreamDeckContextAdapter,
+ solver solver.Solver,
+ previewAction action.PreviewAction,
+) controllers.VMixController {
+ return &vmixController{
+ vMixAdapter: vmixAdapter,
+ streamDeckAdapter: streamDeckAdapter,
+ solver: solver,
+ previewAction: previewAction,
+ }
+}
+
+func (v *vmixController) OnTally(ctx context.Context, host string, tally *vmixtcp.TallyResponse) error {
+ if err := v.previewAction.Tally(ctx, host, tally); err != nil {
+ return xerrors.Errorf("failed to trigger tally: %w", err)
+ }
+ return nil
+}
+
+func (v *vmixController) OnXML(ctx context.Context, host string, xr *vmixtcp.XMLResponse) error {
+ ctxStrs, found := v.solver.SolveByHost(host)
+ if !found {
+ return xerrors.Errorf("failed to solve host %s", host)
+ }
+
+ inputs := map[string]adapters.Input{}
+ for _, input := range xr.XML.Inputs.Input {
+ num, err := strconv.Atoi(input.Number)
+ if err != nil {
+ return xerrors.Errorf("failed to convert input number %s to int: %w", input.Number, err)
+ }
+ inputs[input.Key] = adapters.Input{
+ Number: num,
+ Name: input.Title,
+ Key: input.Key,
+ }
+ }
+
+ eg := errgroup.Group{}
+ for _, ctxStr := range ctxStrs {
+ ctx := sdcontext.WithContext(ctx, ctxStr)
+ eg.Go(func() error {
+ return v.streamDeckAdapter.SendInputs(ctx, inputs)
+ })
+ }
+ if err := eg.Wait(); err != nil {
+ return xerrors.Errorf("failed to send inputs: %w", err)
+ }
+ return nil
+}
diff --git a/Source/code/di/di.go b/Source/code/di/di.go
new file mode 100644
index 0000000..3c19633
--- /dev/null
+++ b/Source/code/di/di.go
@@ -0,0 +1,48 @@
+package di
+
+import (
+ "context"
+ "os"
+
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/action"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/adapter"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/controller"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/controller/controllers"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/logger"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/setting"
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/solver"
+
+ "github.com/FlowingSPDG/streamdeck"
+)
+
+func InitializeStreamDeckClient(ctx context.Context) *streamdeck.Client {
+ params, err := streamdeck.ParseRegistrationParams(os.Args)
+ if err != nil {
+ panic(err)
+ }
+ streamDeckClient := streamdeck.NewClient(ctx, params)
+ return streamDeckClient
+}
+
+func InitializePreviewActionController(ctx context.Context, streamDeckClient *streamdeck.Client) controllers.PreviewActionController {
+ // misc
+ logger := logger.NewStreamDeckLogger(streamDeckClient)
+ solver := solver.NewSolver(logger)
+ store := setting.NewSettingStore[setting.PreviewSetting]()
+
+ // adapters
+ vMixAdapter := adapter.NewVMixAdapter(logger, solver)
+ streamDeckAdapter := adapter.NewStreamDeckContextAdapter(streamDeckClient)
+
+ // action
+ previewAction := action.NewPreviewAction(logger, streamDeckAdapter, vMixAdapter, solver, store)
+
+ // controller
+ previewController := controller.NewPreviewActionController(previewAction)
+ vMixController := controller.NewVMixController(vMixAdapter, streamDeckAdapter, solver, previewAction)
+
+ // register callbacks
+ vMixAdapter.OnTally(vMixController.OnTally)
+
+ return previewController
+}
diff --git a/Source/code/go.mod b/Source/code/go.mod
new file mode 100644
index 0000000..18555fd
--- /dev/null
+++ b/Source/code/go.mod
@@ -0,0 +1,18 @@
+module github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code
+
+go 1.23
+
+toolchain go1.23.0
+
+require (
+ github.com/FlowingSPDG/streamdeck v0.0.0-20241029015450-9b56615503ca
+ github.com/FlowingSPDG/vmix-go v0.2.4-0.20241029004740-b0a0b2783969
+ github.com/puzpuzpuz/xsync/v3 v3.4.0
+ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da
+)
+
+require (
+ github.com/klauspost/compress v1.10.3 // indirect
+ golang.org/x/sync v0.1.0 // indirect
+ nhooyr.io/websocket v1.8.7 // indirect
+)
diff --git a/Source/code/go.sum b/Source/code/go.sum
new file mode 100644
index 0000000..f73ec5e
--- /dev/null
+++ b/Source/code/go.sum
@@ -0,0 +1,71 @@
+github.com/FlowingSPDG/streamdeck v0.0.0-20241029015450-9b56615503ca h1:/5cxp3ZyLrTRqcYThFu/RN65YUFT1s2TJ6ZspLJEcEM=
+github.com/FlowingSPDG/streamdeck v0.0.0-20241029015450-9b56615503ca/go.mod h1:vHLZvLbEZ5mr8po3/OTntFaGdCjncgfA/SK1nfrP2TU=
+github.com/FlowingSPDG/vmix-go v0.2.4-0.20241029004740-b0a0b2783969 h1:25En4lH5aG+FAniQs7ZqGbQoKhRWCmBiZxJ7X+o42fw=
+github.com/FlowingSPDG/vmix-go v0.2.4-0.20241029004740-b0a0b2783969/go.mod h1:42Vg9eCFOKfPLC5pTiReUJ31ydBOOC5pVuPkUjqMZwk=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
+github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
+github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
+github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
+github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
+github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
+github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
+golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
+nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
diff --git a/Source/code/handlers.go b/Source/code/handlers.go
deleted file mode 100644
index cd3975d..0000000
--- a/Source/code/handlers.go
+++ /dev/null
@@ -1,148 +0,0 @@
-package stdvmix
-
-import (
- "context"
- "encoding/json"
- "fmt"
-
- "github.com/FlowingSPDG/streamdeck"
-)
-
-// SendFuncWillAppearHandler willAppear handler.
-func (s *StdVmix) SendFuncWillAppearHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.WillAppearPayload[SendFunctionPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- return err
- }
-
- if p.Settings.IsDefault() {
- p.Settings.Initialize()
- msg := fmt.Sprintf("Forcing Default value:%v", p.Settings)
- client.LogMessage(msg)
- if err := client.SetSettings(ctx, p.Settings); err != nil {
- return err
- }
- } else {
- s.sendFuncContexts.Store(event.Context, p.Settings)
- }
- return nil
-}
-
-// PreviewWillAppearHandler willAppear handler.
-func (s *StdVmix) PreviewWillAppearHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.WillAppearPayload[PreviewPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- return err
- }
-
- if p.Settings.IsDefault() {
- p.Settings.Initialize()
- msg := fmt.Sprintf("Forcing Default value:%v", p.Settings)
- client.LogMessage(msg)
- if err := client.SetSettings(ctx, p.Settings); err != nil {
- return err
- }
- } else {
- s.previewContexts.Store(event.Context, p.Settings)
- }
- return nil
-}
-
-// PreviewWillAppearHandler willAppear handler.
-func (s *StdVmix) ProgramWillAppearHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.WillAppearPayload[ProgramPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- return err
- }
-
- if p.Settings.IsDefault() {
- p.Settings.Initialize()
- msg := fmt.Sprintf("Forcing Default value:%v", p.Settings)
- client.LogMessage(msg)
- if err := client.SetSettings(ctx, p.Settings); err != nil {
- return err
- }
- } else {
- s.programContexts.Store(event.Context, p.Settings)
- }
- return nil
-}
-
-// SendFuncKeyDownHandler keyDown handler
-func (s *StdVmix) SendFuncKeyDownHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.KeyDownPayload[SendFunctionPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- client.ShowAlert(ctx)
- return err
- }
-
- client.LogMessage("KeyDownHandler")
- client.LogMessage(fmt.Sprintf("settings for this context:%v", p.Settings))
-
- if err := p.Settings.Execute(); err != nil {
- client.ShowAlert(ctx)
- return err
- }
- return client.ShowOk(ctx)
-}
-
-// PreviewKeyDownHandler keyDown handler
-func (s *StdVmix) PreviewKeyDownHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.KeyDownPayload[PreviewPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- return err
- }
-
- client.LogMessage("KeyDownHandler")
- client.LogMessage(fmt.Sprintf("settings for this context:%v", p.Settings))
-
- if err := p.Settings.Execute(); err != nil {
- client.ShowAlert(ctx)
- return err
- }
- return client.ShowOk(ctx)
-}
-
-// ProgramKeyDownHandler keyDown handler
-func (s *StdVmix) ProgramKeyDownHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.KeyDownPayload[ProgramPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- return err
- }
-
- client.LogMessage("KeyDownHandler")
- client.LogMessage(fmt.Sprintf("settings for this context:%v", p.Settings))
-
- if err := p.Settings.Execute(); err != nil {
- client.ShowAlert(ctx)
- return err
- }
- return client.ShowOk(ctx)
-}
-
-func (s *StdVmix) SendFuncDidReceiveSettingsHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.DidReceiveSettingsPayload[SendFunctionPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- return err
- }
- s.sendFuncContexts.Store(event.Context, p.Settings)
- return nil
-}
-
-func (s *StdVmix) PreviewDidReceiveSettingsHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.DidReceiveSettingsPayload[PreviewPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- return err
- }
- s.previewContexts.Store(event.Context, p.Settings)
- return nil
-}
-
-func (s *StdVmix) ProgramDidReceiveSettingsHandler(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
- p := streamdeck.DidReceiveSettingsPayload[ProgramPI]{}
- if err := json.Unmarshal(event.Payload, &p); err != nil {
- return err
- }
- s.programContexts.Store(event.Context, p.Settings)
- return nil
-}
diff --git a/Source/code/logger/logger.go b/Source/code/logger/logger.go
new file mode 100644
index 0000000..6280311
--- /dev/null
+++ b/Source/code/logger/logger.go
@@ -0,0 +1,25 @@
+package logger
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/logger/loggers"
+
+ "github.com/FlowingSPDG/streamdeck"
+)
+
+type streamDeckLogger struct {
+ client *streamdeck.Client
+}
+
+func NewStreamDeckLogger(client *streamdeck.Client) loggers.Logger {
+ return &streamDeckLogger{
+ client: client,
+ }
+}
+
+func (l *streamDeckLogger) LogMessage(ctx context.Context, format string, args ...any) error {
+ msg := fmt.Sprintf(format, args...)
+ return l.client.LogMessage(ctx, msg)
+}
diff --git a/Source/code/logger/loggers/loggers.go b/Source/code/logger/loggers/loggers.go
new file mode 100644
index 0000000..3add7a9
--- /dev/null
+++ b/Source/code/logger/loggers/loggers.go
@@ -0,0 +1,7 @@
+package loggers
+
+import "context"
+
+type Logger interface {
+ LogMessage(ctx context.Context, format string, args ...any) error
+}
diff --git a/Source/code/pi.go b/Source/code/pi.go
deleted file mode 100644
index 883daa4..0000000
--- a/Source/code/pi.go
+++ /dev/null
@@ -1,226 +0,0 @@
-package stdvmix
-
-import (
- "fmt"
- "reflect"
-
- vmixhttp "github.com/FlowingSPDG/vmix-go/http"
-)
-
-// SendFunctionPI Settings for each button to save persistantly on action instance
-type SendFunctionPI struct {
- Host string `json:"host"`
- Port int `json:"port,string"`
- Input string `json:"input"`
- Inputs []input `json:"inputs"`
- Name string `json:"name"`
- Queries []Query `json:"queries"`
-}
-
-type Query struct {
- Key string `json:"key"`
- Value string `json:"value"`
-}
-
-func (p SendFunctionPI) IsDefault() bool {
- return reflect.ValueOf(p).IsZero()
-}
-
-func (p *SendFunctionPI) Initialize() {
- p.Host = "localhost"
- p.Port = 8088
- p.Input = "0"
- p.Name = "PreviewInput"
- p.Inputs = []input{}
- p.Queries = []Query{}
-}
-
-func (p SendFunctionPI) Execute() error {
- vc, err := vmixhttp.NewClient(p.Host, p.Port)
- if err != nil {
- return err
- }
- params := make(map[string]string)
- for _, query := range p.Queries {
- params[query.Key] = query.Value
- }
- return vc.SendFunction(p.Name, params)
-}
-
-// UpdateInputs 自身のInputsを更新する(本当は同じリクエストを何度も送りたくないのでキャッシュしたい)
-func (p *SendFunctionPI) UpdateInputs() error {
- if p.Host == "" || p.Port == 0 {
- return nil // HostかPortがゼロ値の場合何もしない
- }
- vc, err := vmixhttp.NewClient(p.Host, p.Port)
- if err != nil {
- return err
- }
- // スライスをリセットして更新
- p.Inputs = make([]input, 0, len(vc.Inputs.Input))
- for _, i := range vc.Inputs.Input {
- p.Inputs = append(p.Inputs, input{
- Name: i.Name,
- Key: i.Key,
- Number: int(i.Number),
- })
- }
- return nil
-}
-
-// PreviewPI Property Inspector info for Preview
-type PreviewPI struct {
- Host string `json:"host"`
- Port int `json:"port,string"`
- Input string `json:"input"`
- Inputs []input `json:"inputs"`
- Mix string `json:"mix"`
- Tally bool `json:"tally"`
-}
-
-func (p PreviewPI) IsDefault() bool {
- return reflect.ValueOf(p).IsZero()
-}
-
-func (p *PreviewPI) Initialize() {
- p.Host = "localhost"
- p.Port = 8088
- p.Input = "0"
- p.Inputs = []input{}
- p.Mix = ""
- p.Tally = false
-}
-
-func (p PreviewPI) Execute() error {
- vc, err := vmixhttp.NewClient(p.Host, p.Port)
- if err != nil {
- return err
- }
- params := make(map[string]string)
- params["Input"] = p.Input
- params["Mix"] = p.Mix
- return vc.SendFunction("PreviewInput", params)
-}
-
-// UpdateTally タリーを更新、点灯する必要がある場合trueが帰る
-func (p PreviewPI) UpdateTally() (bool, error) {
- if p.Host == "" || p.Port == 0 {
- return false, nil // HostかPortがゼロ値の場合何もしない
- }
- vc, err := vmixhttp.NewClient(p.Host, p.Port)
- if err != nil {
- return false, err
- }
- // 以下コードだとpanicが起きそう
- // vc.Inputs.Input[vc.Preview-1].Key == p.Input, nil
- for _, input := range vc.Inputs.Input {
- // 一致するinputがあればtrueを返す
- if input.Key != p.Input {
- continue
- }
- return input.Number == vc.Preview, nil
- }
- return false, fmt.Errorf("No input found")
-}
-
-// UpdateInputs 自身のInputsを更新する(本当は同じリクエストを何度も送りたくないのでキャッシュしたい)
-func (p *PreviewPI) UpdateInputs() error {
- if p.Host == "" || p.Port == 0 {
- return nil // HostかPortがゼロ値の場合何もしない
- }
- vc, err := vmixhttp.NewClient(p.Host, p.Port)
- if err != nil {
- return err
- }
- // スライスをリセットして更新
- p.Inputs = make([]input, 0, len(vc.Inputs.Input))
- for _, i := range vc.Inputs.Input {
- p.Inputs = append(p.Inputs, input{
- Name: i.Name,
- Key: i.Key,
- Number: int(i.Number),
- })
- }
- return nil
-}
-
-// ProgramPI Property Inspector info for PGM(Cut)
-type ProgramPI struct {
- Host string `json:"host"`
- Port int `json:"port,string"`
- Input string `json:"input"`
- Inputs []input `json:"inputs"`
- Mix string `json:"mix"`
- CutDirect bool `json:"cut_direct"`
- Tally bool `json:"tally"`
-}
-
-func (p ProgramPI) IsDefault() bool {
- return reflect.ValueOf(p).IsZero()
-}
-
-func (p *ProgramPI) Initialize() {
- p.Host = "localhost"
- p.Port = 8088
- p.Input = "0"
- p.Inputs = []input{}
- p.Mix = ""
- p.CutDirect = false
- p.Tally = false
-}
-
-func (p ProgramPI) Execute() error {
- vc, err := vmixhttp.NewClient(p.Host, p.Port)
- if err != nil {
- return err
- }
- cut := "Cut"
- if p.CutDirect {
- cut = "CutDirect"
- }
- params := make(map[string]string)
- params["Input"] = p.Input
- params["Mix"] = p.Mix
- return vc.SendFunction(cut, params)
-}
-
-// UpdateTally タリーを更新、点灯する必要がある場合trueが帰る
-func (p ProgramPI) UpdateTally() (bool, error) {
- if p.Host == "" || p.Port == 0 {
- return false, nil // HostかPortがゼロ値の場合何もしない
- }
- vc, err := vmixhttp.NewClient(p.Host, p.Port)
- if err != nil {
- return false, err
- }
- // 以下コードだとpanicが起きそう
- // vc.Inputs.Input[vc.Preview-1].Key == p.Input, nil
- for _, input := range vc.Inputs.Input {
- // 一致するinputがあればtrueを返す
- if input.Key != p.Input {
- continue
- }
- return input.Number == vc.Active, nil
- }
- return false, fmt.Errorf("No input found")
-}
-
-func (p *ProgramPI) UpdateInputs() error {
- if p.Host == "" || p.Port == 0 {
- return nil // HostかPortがゼロ値の場合何もしない
- }
- vc, err := vmixhttp.NewClient(p.Host, p.Port)
- if err != nil {
- return err
- }
- // スライスをリセットして更新
- p.Inputs = make([]input, 0, len(vc.Inputs.Input))
- for _, i := range vc.Inputs.Input {
- p.Inputs = append(p.Inputs, input{
- Name: i.Name,
- Key: i.Key,
- Number: int(i.Number),
- })
- }
- return nil
-}
diff --git a/Source/code/setting/preview.go b/Source/code/setting/preview.go
new file mode 100644
index 0000000..9f4bde9
--- /dev/null
+++ b/Source/code/setting/preview.go
@@ -0,0 +1,8 @@
+package setting
+
+type PreviewSetting struct {
+ Host string `json:"dest"`
+ Input int `json:"input"`
+ Mix *int `json:"mix"`
+ Tally bool `json:"tally"`
+}
diff --git a/Source/code/setting/setting.go b/Source/code/setting/setting.go
new file mode 100644
index 0000000..af5a75b
--- /dev/null
+++ b/Source/code/setting/setting.go
@@ -0,0 +1,38 @@
+package setting
+
+import "github.com/puzpuzpuz/xsync/v3"
+
+// StreamDeckのcontext(string)から実際のPIデータを型情報込みで引き抜く必要がある
+
+type SettingStore[T any] interface {
+ Load(key string) (value *T, ok bool)
+ LoadOrStore(key string, value *T) (actual *T, ok bool)
+ Store(key string, setting *T)
+ Delete(key string)
+}
+
+func NewSettingStore[T any]() SettingStore[T] {
+ return &settingStore[T]{
+ m: xsync.NewMapOf[string, *T](),
+ }
+}
+
+type settingStore[T any] struct {
+ m *xsync.MapOf[string, *T]
+}
+
+func (s *settingStore[T]) Store(key string, setting *T) {
+ s.m.Store(key, setting)
+}
+
+func (s *settingStore[T]) Load(key string) (value *T, ok bool) {
+ return s.m.Load(key)
+}
+
+func (s *settingStore[T]) LoadOrStore(key string, value *T) (actual *T, ok bool) {
+ return s.m.LoadOrStore(key, value)
+}
+
+func (s *settingStore[T]) Delete(key string) {
+ s.m.Delete(key)
+}
diff --git a/Source/code/solver/solver.go b/Source/code/solver/solver.go
new file mode 100644
index 0000000..d945434
--- /dev/null
+++ b/Source/code/solver/solver.go
@@ -0,0 +1,79 @@
+package solver
+
+import (
+ "slices"
+
+ "github.com/FlowingSPDG/streamdeck-vmix-plugin/Source/code/logger/loggers"
+ "github.com/puzpuzpuz/xsync/v3"
+)
+
+// Solver solves the mapping between vMix host and StreamDeck contexts.
+type Solver interface {
+ SolveByContext(context string) (host string, ok bool)
+ SolveByHost(host string) (contexts []string, ok bool)
+
+ AddHost(host string, context string)
+
+ RemoveContext(context string) (hostRemoved bool)
+}
+
+type solver struct {
+ logger loggers.Logger
+ hostContexts *xsync.MapOf[string, []string]
+}
+
+// NewSolver creates a new Solver.
+func NewSolver(logger loggers.Logger) Solver {
+ return &solver{
+ logger: logger,
+ hostContexts: xsync.NewMapOf[string, []string](),
+ }
+}
+
+func (s *solver) AddHost(host string, context string) {
+ actal, loaded := s.hostContexts.LoadOrStore(host, []string{context})
+ if loaded {
+ actal = append(actal, context)
+ s.hostContexts.Store(host, actal)
+ }
+}
+
+func (s *solver) RemoveContext(context string) bool {
+ removed := false
+ s.logger.LogMessage(nil, "removing context: %s", context)
+ s.hostContexts.Range(func(host string, contexts []string) bool {
+ contexts = slices.DeleteFunc(contexts, func(c string) bool {
+ return c == context
+ })
+
+ if len(contexts) == 0 {
+ s.logger.LogMessage(nil, "destination %s is no longer used. delete!", host)
+ s.hostContexts.Delete(host)
+ removed = true
+ return false
+ }
+
+ s.hostContexts.Store(host, contexts)
+ return true
+ })
+ return removed
+}
+
+func (s *solver) SolveByContext(context string) (host string, ok bool) {
+ ok = false
+ s.hostContexts.Range(func(h string, contexts []string) bool {
+ for _, c := range contexts {
+ if c == context {
+ host = h
+ ok = true
+ return false
+ }
+ }
+ return true
+ })
+ return
+}
+
+func (s *solver) SolveByHost(host string) (contexts []string, ok bool) {
+ return s.hostContexts.Load(host)
+}
diff --git a/Source/manifest.json b/Source/manifest.json
index 30de02b..1e027be 100644
--- a/Source/manifest.json
+++ b/Source/manifest.json
@@ -1,7 +1,7 @@
{
"Actions": [
{
- "Name": "vMix Function",
+ "Name": "Send Shortcut",
"States": [
{
"Image": "images/icon",
@@ -9,14 +9,14 @@
"FontSize": "24"
}
],
- "PropertyInspectorPath": "inspector/function.html",
+ "PropertyInspectorPath": "inspector/index.html",
"SupportedInMultiActions": true,
"Tooltip": "send vMix function",
"UUID": "dev.flowingspdg.vmix.function",
"Icon": "images/icon"
},
{
- "Name": "vMix Preview",
+ "Name": "Preview",
"States": [
{
"Image": "images/icon",
@@ -24,14 +24,14 @@
"FontSize": "24"
}
],
- "PropertyInspectorPath": "inspector/preview.html",
+ "PropertyInspectorPath": "inspector/index.html",
"SupportedInMultiActions": true,
"Tooltip": "Preview vMix input",
"UUID": "dev.flowingspdg.vmix.preview",
"Icon": "images/icon"
},
{
- "Name": "vMix Program(Cut)",
+ "Name": "Program",
"States": [
{
"Image": "images/icon",
@@ -39,11 +39,26 @@
"FontSize": "24"
}
],
- "PropertyInspectorPath": "inspector/program.html",
+ "PropertyInspectorPath": "inspector/index.html",
"SupportedInMultiActions": true,
"Tooltip": "Take vMix input",
"UUID": "dev.flowingspdg.vmix.program",
"Icon": "images/icon"
+ },
+ {
+ "Name": "Activator",
+ "States": [
+ {
+ "Image": "images/icon",
+ "TitleAlignment": "middle",
+ "FontSize": "24"
+ }
+ ],
+ "PropertyInspectorPath": "inspector/index.html",
+ "SupportedInMultiActions": false,
+ "Tooltip": "Activators e.g. Tally for specific input",
+ "UUID": "dev.flowingspdg.vmix.activator",
+ "Icon": "images/icon"
}
],
"SDKVersion": 2,
@@ -56,7 +71,7 @@
"Name": "vMix [FlowingSPDG]",
"Icon": "images/icon",
"URL": "https://github.com/FlowingSPDG/streamdeck-vmix-plugin",
- "Version": "0.5.4",
+ "Version": "0.7.0",
"OS": [
{
"Platform": "windows",
diff --git a/Source/pi/.eslintrc.cjs b/Source/pi/.eslintrc.cjs
new file mode 100644
index 0000000..8ae6157
--- /dev/null
+++ b/Source/pi/.eslintrc.cjs
@@ -0,0 +1,19 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ 'plugin:@stylistic/recommended-extends',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/Source/pi/.gitignore b/Source/pi/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/Source/pi/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/Source/pi/README.md b/Source/pi/README.md
new file mode 100644
index 0000000..0d6babe
--- /dev/null
+++ b/Source/pi/README.md
@@ -0,0 +1,30 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default {
+ // other rules...
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ project: ['./tsconfig.json', './tsconfig.node.json'],
+ tsconfigRootDir: __dirname,
+ },
+}
+```
+
+- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
+- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
diff --git a/Source/pi/caret.svg b/Source/pi/caret.svg
deleted file mode 100644
index b69162a..0000000
--- a/Source/pi/caret.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/Source/pi/check.svg b/Source/pi/check.svg
deleted file mode 100644
index 5b96af0..0000000
--- a/Source/pi/check.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/Source/pi/components.json b/Source/pi/components.json
new file mode 100644
index 0000000..ff3a3d5
--- /dev/null
+++ b/Source/pi/components.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.js",
+ "css": "app/globals.css",
+ "baseColor": "gray",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils"
+ }
+}
\ No newline at end of file
diff --git a/Source/pi/function.html b/Source/pi/function.html
deleted file mode 100644
index e448b5e..0000000
--- a/Source/pi/function.html
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
- vMix
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Source/pi/index.html b/Source/pi/index.html
new file mode 100644
index 0000000..38f492d
--- /dev/null
+++ b/Source/pi/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ PropertyInspector
+
+
+
+
+
+
diff --git a/Source/pi/package-lock.json b/Source/pi/package-lock.json
new file mode 100644
index 0000000..f18ce7b
--- /dev/null
+++ b/Source/pi/package-lock.json
@@ -0,0 +1,4662 @@
+{
+ "name": "pi",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "pi",
+ "version": "0.0.0",
+ "dependencies": {
+ "@radix-ui/react-checkbox": "^1.0.4",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-scroll-area": "^1.0.5",
+ "@radix-ui/react-select": "^2.0.0",
+ "@radix-ui/react-slot": "^1.0.2",
+ "class-variance-authority": "^0.7.0",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.378.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "tailwind-merge": "^2.3.0",
+ "tailwindcss-animate": "^1.0.7"
+ },
+ "devDependencies": {
+ "@stylistic/eslint-plugin": "^2.1.0",
+ "@types/node": "^20.12.12",
+ "@types/react": "^18.2.66",
+ "@types/react-dom": "^18.2.22",
+ "@typescript-eslint/eslint-plugin": "^7.9.0",
+ "@typescript-eslint/parser": "^7.9.0",
+ "@vitejs/plugin-react-swc": "^3.5.0",
+ "eslint": "^8.57.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.6",
+ "tailwindcss": "^3.4.3",
+ "typescript": "^5.5.2",
+ "vite": "^5.2.0",
+ "vite-plugin-singlefile": "^2.0.1"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz",
+ "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
+ "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
+ "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
+ "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
+ "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
+ "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
+ "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
+ "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
+ "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
+ "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
+ "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
+ "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
+ "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
+ "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
+ "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
+ "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
+ "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
+ "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
+ "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
+ "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
+ "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
+ "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+ "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz",
+ "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.0"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.6.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz",
+ "integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==",
+ "dependencies": {
+ "@floating-ui/core": "^1.0.0",
+ "@floating-ui/utils": "^0.2.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz",
+ "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==",
+ "dependencies": {
+ "@floating-ui/dom": "^1.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz",
+ "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw=="
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "dev": true
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@radix-ui/number": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz",
+ "integrity": "sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ }
+ },
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz",
+ "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ }
+ },
+ "node_modules/@radix-ui/react-arrow": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz",
+ "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-primitive": "1.0.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-checkbox": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz",
+ "integrity": "sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/primitive": "1.0.1",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-presence": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-use-controllable-state": "1.0.1",
+ "@radix-ui/react-use-previous": "1.0.1",
+ "@radix-ui/react-use-size": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz",
+ "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-slot": "1.0.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
+ "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz",
+ "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz",
+ "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz",
+ "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/primitive": "1.0.1",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-use-callback-ref": "1.0.1",
+ "@radix-ui/react-use-escape-keydown": "1.0.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz",
+ "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz",
+ "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-use-callback-ref": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
+ "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-use-layout-effect": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
+ "integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-primitive": "1.0.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popper": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz",
+ "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.0.3",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-use-callback-ref": "1.0.1",
+ "@radix-ui/react-use-layout-effect": "1.0.1",
+ "@radix-ui/react-use-rect": "1.0.1",
+ "@radix-ui/react-use-size": "1.0.1",
+ "@radix-ui/rect": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz",
+ "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-primitive": "1.0.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz",
+ "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-use-layout-effect": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz",
+ "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-slot": "1.0.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-scroll-area": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.5.tgz",
+ "integrity": "sha512-b6PAgH4GQf9QEn8zbT2XUHpW5z8BzqEc7Kl11TwDrvuTrxlkcjTD5qa/bxgKr+nmuXKu4L/W5UZ4mlP/VG/5Gw==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/number": "1.0.1",
+ "@radix-ui/primitive": "1.0.1",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-direction": "1.0.1",
+ "@radix-ui/react-presence": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-use-callback-ref": "1.0.1",
+ "@radix-ui/react-use-layout-effect": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.0.0.tgz",
+ "integrity": "sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/number": "1.0.1",
+ "@radix-ui/primitive": "1.0.1",
+ "@radix-ui/react-collection": "1.0.3",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-direction": "1.0.1",
+ "@radix-ui/react-dismissable-layer": "1.0.5",
+ "@radix-ui/react-focus-guards": "1.0.1",
+ "@radix-ui/react-focus-scope": "1.0.4",
+ "@radix-ui/react-id": "1.0.1",
+ "@radix-ui/react-popper": "1.1.3",
+ "@radix-ui/react-portal": "1.0.4",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-slot": "1.0.2",
+ "@radix-ui/react-use-callback-ref": "1.0.1",
+ "@radix-ui/react-use-controllable-state": "1.0.1",
+ "@radix-ui/react-use-layout-effect": "1.0.1",
+ "@radix-ui/react-use-previous": "1.0.1",
+ "@radix-ui/react-visually-hidden": "1.0.3",
+ "aria-hidden": "^1.1.1",
+ "react-remove-scroll": "2.5.5"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
+ "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-compose-refs": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz",
+ "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz",
+ "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-use-callback-ref": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-escape-keydown": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz",
+ "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-use-callback-ref": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz",
+ "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz",
+ "integrity": "sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-rect": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz",
+ "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/rect": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-size": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz",
+ "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-use-layout-effect": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz",
+ "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-primitive": "1.0.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/rect": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz",
+ "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
+ "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz",
+ "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz",
+ "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz",
+ "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz",
+ "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz",
+ "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz",
+ "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz",
+ "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz",
+ "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz",
+ "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz",
+ "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz",
+ "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz",
+ "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz",
+ "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz",
+ "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz",
+ "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@stylistic/eslint-plugin": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.1.0.tgz",
+ "integrity": "sha512-cBBowKP2u/+uE5CzgH5w8pE9VKqcM7BXdIDPIbGt2rmLJGnA6MJPr9vYGaqgMoJFs7R/FzsMQerMvvEP40g2uw==",
+ "dev": true,
+ "dependencies": {
+ "@stylistic/eslint-plugin-js": "2.1.0",
+ "@stylistic/eslint-plugin-jsx": "2.1.0",
+ "@stylistic/eslint-plugin-plus": "2.1.0",
+ "@stylistic/eslint-plugin-ts": "2.1.0",
+ "@types/eslint": "^8.56.10"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.40.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-js": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.1.0.tgz",
+ "integrity": "sha512-gdXUjGNSsnY6nPyqxu6lmDTtVrwCOjun4x8PUn0x04d5ucLI74N3MT1Q0UhdcOR9No3bo5PGDyBgXK+KmD787A==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint": "^8.56.10",
+ "acorn": "^8.11.3",
+ "eslint-visitor-keys": "^4.0.0",
+ "espree": "^10.0.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.40.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-js/node_modules/eslint-visitor-keys": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
+ "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-js/node_modules/espree": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz",
+ "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.11.3",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-jsx": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.1.0.tgz",
+ "integrity": "sha512-mMD7S+IndZo2vxmwpHVTCwx2O1VdtE5tmpeNwgaEcXODzWV1WTWpnsc/PECQKIr/mkLPFWiSIqcuYNhQ/3l6AQ==",
+ "dev": true,
+ "dependencies": {
+ "@stylistic/eslint-plugin-js": "^2.1.0",
+ "@types/eslint": "^8.56.10",
+ "estraverse": "^5.3.0",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.40.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-jsx/node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-plus": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.1.0.tgz",
+ "integrity": "sha512-S5QAlgYXESJaSBFhBSBLZy9o36gXrXQwWSt6QkO+F0SrT9vpV5JF/VKoh+ojO7tHzd8Ckmyouq02TT9Sv2B0zQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint": "^8.56.10",
+ "@typescript-eslint/utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin-ts": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.1.0.tgz",
+ "integrity": "sha512-2ioFibufHYBALx2TBrU4KXovCkN8qCqcb9yIHc0fyOfTaO5jw4d56WW7YRcF3Zgde6qFyXwAN6z/+w4pnmos1g==",
+ "dev": true,
+ "dependencies": {
+ "@stylistic/eslint-plugin-js": "2.1.0",
+ "@types/eslint": "^8.56.10",
+ "@typescript-eslint/utils": "^7.8.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.40.0"
+ }
+ },
+ "node_modules/@swc/core": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.7.tgz",
+ "integrity": "sha512-U4qJRBefIJNJDRCCiVtkfa/hpiZ7w0R6kASea+/KLp+vkus3zcLSB8Ub8SvKgTIxjWpwsKcZlPf5nrv4ls46SQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@swc/counter": "^0.1.2",
+ "@swc/types": "0.1.7"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/swc"
+ },
+ "optionalDependencies": {
+ "@swc/core-darwin-arm64": "1.5.7",
+ "@swc/core-darwin-x64": "1.5.7",
+ "@swc/core-linux-arm-gnueabihf": "1.5.7",
+ "@swc/core-linux-arm64-gnu": "1.5.7",
+ "@swc/core-linux-arm64-musl": "1.5.7",
+ "@swc/core-linux-x64-gnu": "1.5.7",
+ "@swc/core-linux-x64-musl": "1.5.7",
+ "@swc/core-win32-arm64-msvc": "1.5.7",
+ "@swc/core-win32-ia32-msvc": "1.5.7",
+ "@swc/core-win32-x64-msvc": "1.5.7"
+ },
+ "peerDependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependenciesMeta": {
+ "@swc/helpers": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@swc/core-darwin-arm64": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.7.tgz",
+ "integrity": "sha512-bZLVHPTpH3h6yhwVl395k0Mtx8v6CGhq5r4KQdAoPbADU974Mauz1b6ViHAJ74O0IVE5vyy7tD3OpkQxL/vMDQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-darwin-x64": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.7.tgz",
+ "integrity": "sha512-RpUyu2GsviwTc2qVajPL0l8nf2vKj5wzO3WkLSHAHEJbiUZk83NJrZd1RVbEknIMO7+Uyjh54hEh8R26jSByaw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm-gnueabihf": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.7.tgz",
+ "integrity": "sha512-cTZWTnCXLABOuvWiv6nQQM0hP6ZWEkzdgDvztgHI/+u/MvtzJBN5lBQ2lue/9sSFYLMqzqff5EHKlFtrJCA9dQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-gnu": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.7.tgz",
+ "integrity": "sha512-hoeTJFBiE/IJP30Be7djWF8Q5KVgkbDtjySmvYLg9P94bHg9TJPSQoC72tXx/oXOgXvElDe/GMybru0UxhKx4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-musl": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.7.tgz",
+ "integrity": "sha512-+NDhK+IFTiVK1/o7EXdCeF2hEzCiaRSrb9zD7X2Z7inwWlxAntcSuzZW7Y6BRqGQH89KA91qYgwbnjgTQ22PiQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-gnu": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.7.tgz",
+ "integrity": "sha512-25GXpJmeFxKB+7pbY7YQLhWWjkYlR+kHz5I3j9WRl3Lp4v4UD67OGXwPe+DIcHqcouA1fhLhsgHJWtsaNOMBNg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-musl": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.7.tgz",
+ "integrity": "sha512-0VN9Y5EAPBESmSPPsCJzplZHV26akC0sIgd3Hc/7S/1GkSMoeuVL+V9vt+F/cCuzr4VidzSkqftdP3qEIsXSpg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-arm64-msvc": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.7.tgz",
+ "integrity": "sha512-RtoNnstBwy5VloNCvmvYNApkTmuCe4sNcoYWpmY7C1+bPR+6SOo8im1G6/FpNem8AR5fcZCmXHWQ+EUmRWJyuA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-ia32-msvc": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.7.tgz",
+ "integrity": "sha512-Xm0TfvcmmspvQg1s4+USL3x8D+YPAfX2JHygvxAnCJ0EHun8cm2zvfNBcsTlnwYb0ybFWXXY129aq1wgFC9TpQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-x64-msvc": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.7.tgz",
+ "integrity": "sha512-tp43WfJLCsKLQKBmjmY/0vv1slVywR5Q4qKjF5OIY8QijaEW7/8VwPyUyVoJZEnDgv9jKtUTG5PzqtIYPZGnyg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
+ "dev": true
+ },
+ "node_modules/@swc/types": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.7.tgz",
+ "integrity": "sha512-scHWahbHF0eyj3JsxG9CFJgFdFNaVQCNAimBlT6PzS3n/HptxqREjsm4OH6AN3lYcffZYSPxXW8ua2BEHp0lJQ==",
+ "dev": true,
+ "dependencies": {
+ "@swc/counter": "^0.1.3"
+ }
+ },
+ "node_modules/@types/eslint": {
+ "version": "8.56.10",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz",
+ "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+ "dev": true
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.12.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
+ "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.12",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
+ "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
+ "devOptional": true
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.2",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz",
+ "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==",
+ "devOptional": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.0",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz",
+ "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==",
+ "devOptional": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz",
+ "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "7.9.0",
+ "@typescript-eslint/type-utils": "7.9.0",
+ "@typescript-eslint/utils": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.3.1",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^7.0.0",
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz",
+ "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "7.9.0",
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/typescript-estree": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz",
+ "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz",
+ "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "7.9.0",
+ "@typescript-eslint/utils": "7.9.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz",
+ "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz",
+ "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz",
+ "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "7.9.0",
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/typescript-estree": "7.9.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz",
+ "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
+ "node_modules/@vitejs/plugin-react-swc": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.6.0.tgz",
+ "integrity": "sha512-XFRbsGgpGxGzEV5i5+vRiro1bwcIaZDIdBRP16qwm+jP68ue/S8FJTBEgOeojtVDYrbSua3XFp71kC8VJE6v+g==",
+ "dev": true,
+ "dependencies": {
+ "@swc/core": "^1.3.107"
+ },
+ "peerDependencies": {
+ "vite": "^4 || ^5"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/aria-hidden": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz",
+ "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/class-variance-authority": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz",
+ "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==",
+ "dependencies": {
+ "clsx": "2.0.0"
+ },
+ "funding": {
+ "url": "https://joebell.co.uk"
+ }
+ },
+ "node_modules/class-variance-authority/node_modules/clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "devOptional": true
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
+ },
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ },
+ "node_modules/esbuild": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
+ "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.20.2",
+ "@esbuild/android-arm": "0.20.2",
+ "@esbuild/android-arm64": "0.20.2",
+ "@esbuild/android-x64": "0.20.2",
+ "@esbuild/darwin-arm64": "0.20.2",
+ "@esbuild/darwin-x64": "0.20.2",
+ "@esbuild/freebsd-arm64": "0.20.2",
+ "@esbuild/freebsd-x64": "0.20.2",
+ "@esbuild/linux-arm": "0.20.2",
+ "@esbuild/linux-arm64": "0.20.2",
+ "@esbuild/linux-ia32": "0.20.2",
+ "@esbuild/linux-loong64": "0.20.2",
+ "@esbuild/linux-mips64el": "0.20.2",
+ "@esbuild/linux-ppc64": "0.20.2",
+ "@esbuild/linux-riscv64": "0.20.2",
+ "@esbuild/linux-s390x": "0.20.2",
+ "@esbuild/linux-x64": "0.20.2",
+ "@esbuild/netbsd-x64": "0.20.2",
+ "@esbuild/openbsd-x64": "0.20.2",
+ "@esbuild/sunos-x64": "0.20.2",
+ "@esbuild/win32-arm64": "0.20.2",
+ "@esbuild/win32-ia32": "0.20.2",
+ "@esbuild/win32-x64": "0.20.2"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz",
+ "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.7.tgz",
+ "integrity": "sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=7"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true
+ },
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globals/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "dependencies": {
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
+ "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
+ "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
+ "engines": {
+ "node": "14 || >=16.14"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.378.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.378.0.tgz",
+ "integrity": "sha512-u6EPU8juLUk9ytRcyapkWI18epAv3RU+6+TC23ivjR0e+glWKBobFeSgRwOIJihzktILQuy6E0E80P2jVTDR5g==",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+ "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz",
+ "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-load-config/node_modules/lilconfig": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
+ "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
+ "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.11"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.16",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
+ "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-remove-scroll": {
+ "version": "2.5.5",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz",
+ "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==",
+ "dependencies": {
+ "react-remove-scroll-bar": "^2.3.3",
+ "react-style-singleton": "^2.2.1",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.0",
+ "use-sidecar": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-remove-scroll-bar": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz",
+ "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==",
+ "dependencies": {
+ "react-style-singleton": "^2.2.1",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-style-singleton": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
+ "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==",
+ "dependencies": {
+ "get-nonce": "^1.0.0",
+ "invariant": "^2.2.4",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz",
+ "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "1.0.5"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.17.2",
+ "@rollup/rollup-android-arm64": "4.17.2",
+ "@rollup/rollup-darwin-arm64": "4.17.2",
+ "@rollup/rollup-darwin-x64": "4.17.2",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.17.2",
+ "@rollup/rollup-linux-arm-musleabihf": "4.17.2",
+ "@rollup/rollup-linux-arm64-gnu": "4.17.2",
+ "@rollup/rollup-linux-arm64-musl": "4.17.2",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2",
+ "@rollup/rollup-linux-riscv64-gnu": "4.17.2",
+ "@rollup/rollup-linux-s390x-gnu": "4.17.2",
+ "@rollup/rollup-linux-x64-gnu": "4.17.2",
+ "@rollup/rollup-linux-x64-musl": "4.17.2",
+ "@rollup/rollup-win32-arm64-msvc": "4.17.2",
+ "@rollup/rollup-win32-ia32-msvc": "4.17.2",
+ "@rollup/rollup-win32-x64-msvc": "4.17.2",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
+ "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "10.3.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz",
+ "integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.6",
+ "minimatch": "^9.0.1",
+ "minipass": "^7.0.4",
+ "path-scurry": "^1.11.0"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tailwind-merge": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.3.0.tgz",
+ "integrity": "sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==",
+ "dependencies": {
+ "@babel/runtime": "^7.24.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
+ "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.5.3",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.0",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.0",
+ "lilconfig": "^2.1.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.0.0",
+ "postcss": "^8.4.23",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.1",
+ "postcss-nested": "^6.0.1",
+ "postcss-selector-parser": "^6.0.11",
+ "resolve": "^1.22.2",
+ "sucrase": "^3.32.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tailwindcss-animate": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
+ "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.31.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz",
+ "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-api-utils": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
+ "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz",
+ "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-callback-ref": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz",
+ "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sidecar": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
+ "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==",
+ "dependencies": {
+ "detect-node-es": "^1.1.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/vite": {
+ "version": "5.2.11",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
+ "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.20.1",
+ "postcss": "^8.4.38",
+ "rollup": "^4.13.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite-plugin-singlefile": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/vite-plugin-singlefile/-/vite-plugin-singlefile-2.0.1.tgz",
+ "integrity": "sha512-J74tfN6TE4fz0Hp7E1+dmVTmCpyazv4yuIpR6jd22Kq76d2CQDSQx3wDiHX8LT02f922V+YrLhRq2VIk/UYrig==",
+ "dev": true,
+ "dependencies": {
+ "micromatch": "^4.0.5"
+ },
+ "engines": {
+ "node": ">18.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^4.12.0",
+ "vite": "^5.1.4"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz",
+ "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/Source/pi/package.json b/Source/pi/package.json
new file mode 100644
index 0000000..e90b879
--- /dev/null
+++ b/Source/pi/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "pi",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "format": "eslint --fix . --ext ts,tsx",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@radix-ui/react-checkbox": "^1.0.4",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-scroll-area": "^1.0.5",
+ "@radix-ui/react-select": "^2.0.0",
+ "@radix-ui/react-slot": "^1.0.2",
+ "class-variance-authority": "^0.7.0",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.378.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "tailwind-merge": "^2.3.0",
+ "tailwindcss-animate": "^1.0.7"
+ },
+ "devDependencies": {
+ "@stylistic/eslint-plugin": "^2.1.0",
+ "@types/node": "^20.12.12",
+ "@types/react": "^18.2.66",
+ "@types/react-dom": "^18.2.22",
+ "@typescript-eslint/eslint-plugin": "^7.9.0",
+ "@typescript-eslint/parser": "^7.9.0",
+ "@vitejs/plugin-react-swc": "^3.5.0",
+ "eslint": "^8.57.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.6",
+ "tailwindcss": "^3.4.3",
+ "typescript": "^5.5.2",
+ "vite": "^5.2.0",
+ "vite-plugin-singlefile": "^2.0.1"
+ }
+}
diff --git a/Source/pi/preview.html b/Source/pi/preview.html
deleted file mode 100644
index 7de6c57..0000000
--- a/Source/pi/preview.html
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
- vMix
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Mix
-
-
-
-
-
-
-
-
-
diff --git a/Source/pi/program.html b/Source/pi/program.html
deleted file mode 100644
index 0a5aea5..0000000
--- a/Source/pi/program.html
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
- vMix
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Mix
-
-
-
-
-
-
-
Enable CutDirect
-
-
-
-
-
-
-
-
-
diff --git a/Source/pi/sdtools.common.js b/Source/pi/sdtools.common.js
deleted file mode 100644
index 10a9d21..0000000
--- a/Source/pi/sdtools.common.js
+++ /dev/null
@@ -1,325 +0,0 @@
-// ****************************************************************
-// * EasyPI v1.3.3
-// * Author: BarRaider
-// *
-// * JS library to simplify the communication between the
-// * Stream Deck's Property Inspector and the plugin.
-// *
-// * Project page: https://github.com/BarRaider/streamdeck-easypi
-// * Support: http://discord.barraider.com
-// *
-// * Initially forked from Elgato's common.js file
-// ****************************************************************
-
-var websocket = null,
- uuid = null,
- registerEventName = null,
- actionInfo = {},
- inInfo = {},
- runningApps = [],
- isQT = navigator.appVersion.includes('QtWebEngine');
-
-function connectElgatoStreamDeckSocket(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo) {
- uuid = inUUID;
- registerEventName = inRegisterEvent;
- console.log(inUUID, inActionInfo);
- actionInfo = JSON.parse(inActionInfo); // cache the info
- inInfo = JSON.parse(inInfo);
- websocket = new WebSocket('ws://127.0.0.1:' + inPort);
-
- addDynamicStyles(inInfo.colors);
-
- websocket.onopen = websocketOnOpen;
- websocket.onmessage = websocketOnMessage;
-
- // Allow others to get notified that the websocket is created
- var event = new Event('websocketCreate');
- document.dispatchEvent(event);
-
- loadConfiguration(actionInfo.payload.settings);
- initPropertyInspector();
-}
-
-function websocketOnOpen() {
- var json = {
- event: registerEventName,
- uuid: uuid
- };
- websocket.send(JSON.stringify(json));
-
- // Notify the plugin that we are connected
- sendValueToPlugin('propertyInspectorConnected', 'property_inspector');
-}
-
-function websocketOnMessage(evt) {
- // Received message from Stream Deck
- var jsonObj = JSON.parse(evt.data);
-
- if (jsonObj.event === 'didReceiveSettings') {
- var payload = jsonObj.payload;
- loadConfiguration(payload.settings);
- }
- var event = new Event('onmessage',jsonObj.payload);
- document.dispatchEvent(event);
-}
-
-function loadConfiguration(payload) {
- console.log('loadConfiguration');
- console.log(payload);
- for (var key in payload) {
- try {
- var elem = document.getElementById(key);
- if (elem.classList.contains("sdCheckbox")) { // Checkbox
- elem.checked = payload[key];
- }
- else if (elem.classList.contains("sdFile")) { // File
- var elemFile = document.getElementById(elem.id + "Filename");
- elemFile.innerText = payload[key];
- if (!elemFile.innerText) {
- elemFile.innerText = "No file...";
- }
- }
- else if (elem.classList.contains("sdList")) { // Dynamic dropdown
- var textProperty = elem.getAttribute("sdListTextProperty");
- var valueProperty = elem.getAttribute("sdListValueProperty");
- var valueField = elem.getAttribute("sdValueField");
-
- var items = payload[key];
- elem.options.length = 0;
-
- for (var idx = 0; idx < items.length; idx++) {
- var opt = document.createElement('option');
- opt.value = items[idx][valueProperty];
- // for vMix input number
- opt.text = `${items[idx].number} : ${items[idx][textProperty]}`;
- elem.appendChild(opt);
- }
- elem.value = payload[valueField];
- }
- else if (elem.classList.contains("sdHTML")) { // HTML element
- elem.innerHTML = payload[key];
- }
- else { // Normal value
- elem.value = payload[key];
- }
- console.log("Load: " + key + "=" + payload[key]);
- }
- catch (err) {
- console.log("loadConfiguration failed for key: " + key + " - " + err);
- }
- }
-}
-
-function setSettings() {
- var payload = {};
- var elements = document.getElementsByClassName("sdProperty");
-
- Array.prototype.forEach.call(elements, function (elem) {
- var key = elem.id;
- if (elem.classList.contains("sdCheckbox")) { // Checkbox
- payload[key] = elem.checked;
- console.log("Save: " + key + "<=" + payload[key]);
- }
- else if (elem.classList.contains("sdFile")) { // File
- var elemFile = document.getElementById(elem.id + "Filename");
- payload[key] = elem.value;
- if (!elem.value) {
- // Fetch innerText if file is empty (happens when we lose and regain focus to this key)
- payload[key] = elemFile.innerText;
- }
- else {
- // Set value on initial file selection
- elemFile.innerText = elem.value;
- }
- console.log("Save: " + key + "<=" + payload[key]);
- }
- else if (elem.classList.contains("sdList")) { // Dynamic dropdown
- var valueField = elem.getAttribute("sdValueField");
- payload[valueField] = elem.value;
- console.log("Save : " + valueField + "<=" + payload[valueField]);
- }
- else if (elem.classList.contains("sdHTML")) { // HTML element
- var valueField = elem.getAttribute("sdValueField");
- payload[valueField] = elem.innerHTML;
- console.log("Save: " + valueField + "<=" + payload[valueField]);
- }
- else { // Normal value
- payload[key] = elem.value;
- console.log("Save: " + key + "<=" + payload[key]);
- }
- });
- setSettingsToPlugin(payload);
-}
-
-function setSettingsToPlugin(payload) {
- if (websocket && (websocket.readyState === 1)) {
- const json = {
- 'event': 'setSettings',
- 'context': uuid,
- 'payload': payload
- };
- websocket.send(JSON.stringify(json));
- var event = new Event('settingsUpdated');
- document.dispatchEvent(event);
- }
-}
-
-// Sends an entire payload to the sendToPlugin method
-function sendPayloadToPlugin(payload) {
- if (websocket && (websocket.readyState === 1)) {
- const json = {
- 'action': actionInfo['action'],
- 'event': 'sendToPlugin',
- 'context': uuid,
- 'payload': payload
- };
- websocket.send(JSON.stringify(json));
- }
-}
-
-// Sends one value to the sendToPlugin method
-function sendValueToPlugin(value, param) {
- if (websocket && (websocket.readyState === 1)) {
- const json = {
- 'action': actionInfo['action'],
- 'event': 'sendToPlugin',
- 'context': uuid,
- 'payload': {
- [param]: value
- }
- };
- websocket.send(JSON.stringify(json));
- }
-}
-
-function openWebsite() {
- if (websocket && (websocket.readyState === 1)) {
- const json = {
- 'event': 'openUrl',
- 'payload': {
- 'url': 'https://BarRaider.com'
- }
- };
- websocket.send(JSON.stringify(json));
- }
-}
-
-if (!isQT) {
- document.addEventListener('DOMContentLoaded', function () {
- initPropertyInspector();
- });
-}
-
-window.addEventListener('beforeunload', function (e) {
- e.preventDefault();
-
- // Notify the plugin we are about to leave
- sendValueToPlugin('propertyInspectorWillDisappear', 'property_inspector');
-
- // Don't set a returnValue to the event, otherwise Chromium with throw an error.
-});
-
-function prepareDOMElements(baseElement) {
- baseElement = baseElement || document;
-
- /**
- * You could add a 'label' to a textares, e.g. to show the number of charactes already typed
- * or contained in the textarea. This helper updates this label for you.
- */
- baseElement.querySelectorAll('textarea').forEach((e) => {
- const maxl = e.getAttribute('maxlength');
- e.targets = baseElement.querySelectorAll(`[for='${e.id}']`);
- if (e.targets.length) {
- let fn = () => {
- for (let x of e.targets) {
- x.textContent = maxl ? `${e.value.length}/${maxl}` : `${e.value.length}`;
- }
- };
- fn();
- e.onkeyup = fn;
- }
- });
-}
-
-function initPropertyInspector() {
- // Place to add functions
- prepareDOMElements(document);
-}
-
-
-function addDynamicStyles(clrs) {
- const node = document.getElementById('#sdpi-dynamic-styles') || document.createElement('style');
- if (!clrs.mouseDownColor) clrs.mouseDownColor = fadeColor(clrs.highlightColor, -100);
- const clr = clrs.highlightColor.slice(0, 7);
- const clr1 = fadeColor(clr, 100);
- const clr2 = fadeColor(clr, 60);
- const metersActiveColor = fadeColor(clr, -60);
-
- node.setAttribute('id', 'sdpi-dynamic-styles');
- node.innerHTML = `
-
- input[type="radio"]:checked + label span,
- input[type="checkbox"]:checked + label span {
- background-color: ${clrs.highlightColor};
- }
-
- input[type="radio"]:active:checked + label span,
- input[type="radio"]:active + label span,
- input[type="checkbox"]:active:checked + label span,
- input[type="checkbox"]:active + label span {
- background-color: ${clrs.mouseDownColor};
- }
-
- input[type="radio"]:active + label span,
- input[type="checkbox"]:active + label span {
- background-color: ${clrs.buttonPressedBorderColor};
- }
-
- td.selected,
- td.selected:hover,
- li.selected:hover,
- li.selected {
- color: white;
- background-color: ${clrs.highlightColor};
- }
-
- .sdpi-file-label > label:active,
- .sdpi-file-label.file:active,
- label.sdpi-file-label:active,
- label.sdpi-file-info:active,
- input[type="file"]::-webkit-file-upload-button:active,
- button:active {
- background-color: ${clrs.buttonPressedBackgroundColor};
- color: ${clrs.buttonPressedTextColor};
- border-color: ${clrs.buttonPressedBorderColor};
- }
-
- ::-webkit-progress-value,
- meter::-webkit-meter-optimum-value {
- background: linear-gradient(${clr2}, ${clr1} 20%, ${clr} 45%, ${clr} 55%, ${clr2})
- }
-
- ::-webkit-progress-value:active,
- meter::-webkit-meter-optimum-value:active {
- background: linear-gradient(${clr}, ${clr2} 20%, ${metersActiveColor} 45%, ${metersActiveColor} 55%, ${clr})
- }
- `;
- document.body.appendChild(node);
-};
-
-/** UTILITIES */
-
-/*
- Quick utility to lighten or darken a color (doesn't take color-drifting, etc. into account)
- Usage:
- fadeColor('#061261', 100); // will lighten the color
- fadeColor('#200867'), -100); // will darken the color
-*/
-function fadeColor(col, amt) {
- const min = Math.min, max = Math.max;
- const num = parseInt(col.replace(/#/g, ''), 16);
- const r = min(255, max((num >> 16) + amt, 0));
- const g = min(255, max((num & 0x0000FF) + amt, 0));
- const b = min(255, max(((num >> 8) & 0x00FF) + amt, 0));
- return '#' + (g | (b << 8) | (r << 16)).toString(16).padStart(6, 0);
-}
\ No newline at end of file
diff --git a/Source/pi/src/App.css b/Source/pi/src/App.css
new file mode 100644
index 0000000..9864bcf
--- /dev/null
+++ b/Source/pi/src/App.css
@@ -0,0 +1,11 @@
+:root {
+ --radius: 0.125rem;
+}
+
+body {
+ font-family: var(--font-inter), sans-serif;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: var(--font-inter), sans-serif;
+}
\ No newline at end of file
diff --git a/Source/pi/src/App.tsx b/Source/pi/src/App.tsx
new file mode 100644
index 0000000..5d034a8
--- /dev/null
+++ b/Source/pi/src/App.tsx
@@ -0,0 +1,88 @@
+import { useState } from 'react'
+import { SD } from './sd'
+import { Preview, type PreviewSettings } from './components/preview'
+import { Program, type ProgramSettings } from './components/program'
+import type { SendToPropertyInspector, SendInputs, DestinationToInputs } from './types/streamdeck'
+import { Activator, type ActivatorSettings } from './components/activator'
+
+declare global {
+ interface Window {
+ connectElgatoStreamDeckSocket: (
+ inPort: number,
+ inUUID: string,
+ inRegisterEvent: string,
+ inInfo: string,
+ inActionInfo: string
+ ) => void
+ }
+}
+
+function App() {
+ type T = PreviewSettings | ProgramSettings | ActivatorSettings
+ // States
+ const [sd, setSD] = useState | null>(null)
+ const [settings, setSettings] = useState({} as T)
+ const [inputs, setInputs] = useState({})
+
+ // connectElgatoStreamDeckSocket is a function that is called by the Stream Deck software when the Property Inspector is opened.
+ // グローバル変数である必要がある
+ window.connectElgatoStreamDeckSocket = (
+ inPort: number,
+ inUUID: string,
+ inRegisterEvent: string,
+ inInfo: string,
+ inActionInfo: string,
+ ) => {
+ setSD(new SD(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo,
+ {
+ onOpen: () => {
+ console.log('Opened')
+ },
+ OnDidReceiveSettings: (s) => {
+ console.log('Settings received', s)
+ setSettings(s as T)
+ },
+ OnDidReceiveGlobalSettings: (s) => {
+ console.log(s)
+ },
+ OnSendToPropertyInspector: (payload: unknown) => {
+ // カスみてえな型チェック
+ if (!payload) return
+ if (typeof payload !== 'object') return
+ if (!('event' in payload)) return
+
+ if (payload?.event === 'inputs') {
+ const p: SendToPropertyInspector = payload as SendToPropertyInspector
+ console.log('inputs', p.payload.inputs)
+ setInputs(p.payload.inputs)
+ }
+ },
+ },
+
+ // TODO: 型をもっと扱いやすく厳密にする
+ // Actionごとにカスタムしたくなると思うので、もっと冗長性を持たせる
+ // 例えばSettings, コールバック関数を外部から設定できるようにして、StreamDeckとの接続のみを担うコンポーネントを切り出す
+ // actionInfo.action で描画先を変更するのではなく、もっと細かく分ける
+ ))
+
+ // TODO: Apply colours
+ // addDynamicStyles(inInfo.colors);
+ }
+
+ const onSettingsUpdate = (s: T) => {
+ console.log('Updated. sending payload...', s)
+ setSettings(s)
+ sd?.setSettings(s)
+ }
+
+ return (
+ <>
+ { sd?.actionInfo.action === 'dev.flowingspdg.vmix.preview' && }
+ { sd?.actionInfo.action === 'dev.flowingspdg.vmix.program' && }
+ { sd?.actionInfo.action === 'dev.flowingspdg.vmix.activator' && }
+ { sd?.actionInfo.action === 'dev.flowingspdg.vmix.function' && 'NOT YET!' }
+ >
+ )
+}
+
+export default App
diff --git a/Source/pi/src/components/activator.tsx b/Source/pi/src/components/activator.tsx
new file mode 100644
index 0000000..a6070be
--- /dev/null
+++ b/Source/pi/src/components/activator.tsx
@@ -0,0 +1,134 @@
+import type { DestinationToInputs } from '../types/streamdeck'
+
+export type ActivatorSettings = {
+ dest: string
+ input: number
+ color: 1 | 2
+ activator: 'Input' | 'InputPreview'
+ | 'Overlay1' | 'Overlay2' | 'Overlay3' | 'Overlay4'
+ | 'InputMix2' | 'InputMix3' | 'InputMix4'
+ | 'InputPreviewMix2' | 'InputPreviewMix3' | 'InputPreviewMix4'
+}
+
+const checkActivator = (activator: string): activator is ActivatorSettings['activator'] => {
+ return ['Input', 'InputPreview', 'Overlay1', 'Overlay2', 'Overlay3', 'Overlay4', 'InputMix2', 'InputMix3', 'InputMix4', 'InputPreviewMix2', 'InputPreviewMix3', 'InputPreviewMix4'].includes(activator)
+}
+
+type ActivatorProps = {
+ settings: ActivatorSettings
+ inputs: DestinationToInputs
+
+ // Callback
+ onUpdate: (settings: ActivatorSettings) => void
+}
+
+export const Activator = (props: ActivatorProps) => {
+ console.log('props: ', props)
+ console.log('inputs: ', props.inputs[props.settings.dest])
+ return (
+
+
+
Host IP
+
props.onUpdate({
+ ...props.settings,
+ dest: e.target.value,
+ })
+ }
+ />
+
+
+
+
Tally Type
+
+
+
+
+
+
+
Tally Color
+
+
+
+
+
+
+
Input
+
+
+
+
+
+
+ )
+}
diff --git a/Source/pi/src/components/preview.tsx b/Source/pi/src/components/preview.tsx
new file mode 100644
index 0000000..5f75e8d
--- /dev/null
+++ b/Source/pi/src/components/preview.tsx
@@ -0,0 +1,87 @@
+import type { DestinationToInputs } from '../types/streamdeck'
+
+export type PreviewSettings = {
+ dest: string
+ input: number
+ mix: number | null
+ tally: boolean
+}
+
+type PreviewProps = {
+ settings: PreviewSettings
+ inputs: DestinationToInputs
+
+ // Callback
+ onUpdate: (settings: PreviewSettings) => void
+}
+
+export const Preview = (props: PreviewProps) => {
+ return (
+
+
+
Host IP
+
props.onUpdate({
+ ...props.settings,
+ dest: e.target.value,
+ })
+ }
+ />
+
+
+
+
Tally
+
+
+ {
+ props.onUpdate({
+ ...props.settings,
+ tally: e.target.checked,
+ })
+ }}
+ />
+
+
+
+
+
+
+
Input
+
+
+
+
+
+
+ )
+}
diff --git a/Source/pi/src/components/program.tsx b/Source/pi/src/components/program.tsx
new file mode 100644
index 0000000..715b522
--- /dev/null
+++ b/Source/pi/src/components/program.tsx
@@ -0,0 +1,102 @@
+import type { DestinationToInputs } from '../types/streamdeck'
+
+export type ProgramSettings = {
+ dest: string
+ input: number
+ mix: number | null
+ tally: boolean
+ transition: string
+}
+
+type ProgramProps = {
+ settings: ProgramSettings
+ inputs: DestinationToInputs
+
+ // Callback
+ onUpdate: (settings: ProgramSettings) => void
+}
+
+export const Program = (props: ProgramProps) => {
+ return (
+
+
+
Host IP
+
props.onUpdate({
+ ...props.settings,
+ dest: e.target.value,
+ })
+ }
+ />
+
+
+
+
Transition
+
props.onUpdate({
+ ...props.settings,
+ transition: e.target.value,
+ })
+ }
+ />
+
+
+
+
Tally
+
+
+ {
+ props.onUpdate({
+ ...props.settings,
+ tally: e.target.checked,
+ })
+ }}
+ />
+
+
+
+
+
+
+
Input
+
+
+
+
+
+
+ )
+}
diff --git a/Source/pi/sdpi.css b/Source/pi/src/index.css
similarity index 76%
rename from Source/pi/sdpi.css
rename to Source/pi/src/index.css
index cf8cc9d..b95e00d 100644
--- a/Source/pi/sdpi.css
+++ b/Source/pi/src/index.css
@@ -1,54 +1,65 @@
.linkspan {
- cursor: pointer;
- color: #7397d2;
- text-decoration: underline;
+ cursor: pointer;
+ color: #7397d2;
+ text-decoration: underline;
}
.titleAlignedSmall {
- font-size:9pt;
- padding-left:33px !important;
+ font-size:9pt;
+ padding-left:33px !important;
}
.small {
- font-size: 9pt !important;
+ font-size: 9pt !important;
}
.leftMargin10 {
- margin-left: 10px;
+ margin-left: 10px;
}
.leftMargin0 {
- margin-left: 0px !important;
+ margin-left: 0px !important;
}
.leftPadding3 {
- padding-left: 3px !important;
+ padding-left: 3px !important;
}
.leftPadding0 {
- padding-left: 0px !important;
+ padding-left: 0px !important;
}
.bright {
- color:#d8d8d8;
+ color:#d8d8d8;
}
.iconLeft {
- background-position: 0px 4px !important;
+ background-position: 0px 4px !important;
}
.summaryIconPadding
{
- padding-left:15px;
+ padding-left:15px;
}
.subMenu {
- border-left: 1px dotted gray;
- padding-left:15px;
- max-width:96%;
- background-color:#323232;
+ border-left: 1px dotted gray;
+ padding-left:15px;
+ max-width:96%;
+ background-color:#323232;
}
+:root {
+ --sdpi-bgcolor: #2D2D2D;
+ --sdpi-background: #3D3D3D;
+ --sdpi-color: #d8d8d8;
+ --sdpi-bordercolor: #3a3a3a;
+ --sdpi-buttonbordercolor: #969696;
+ --sdpi-borderradius: 0px;
+ --sdpi-width: 224px;
+ --sdpi-fontweight: 600;
+ --sdpi-letterspacing: -0.25pt;
+}
html {
--sdpi-bgcolor: #2D2D2D;
@@ -59,16 +70,19 @@ html {
--sdpi-borderradius: 0px;
--sdpi-width: 224px;
--sdpi-fontweight: 600;
- height: 100%;
+ --sdpi-letterspacing: -0.25pt;
+ height: 100%;
width: 100%;
overflow: hidden;
+ touch-action: none;
}
-html, body {
+html,
+body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 9pt;
- background-color: var(--sdpi-bgcolor);
- color: #9a9a9a;
+ background-color: var(--sdpi-bgcolor);
+ color: #9a9a9a;
}
body {
@@ -87,7 +101,8 @@ mark {
color: var(--sdpi-color);
}
-hr, hr2 {
+hr,
+hr2 {
-webkit-margin-before: 1em;
-webkit-margin-after: 1em;
border-style: none;
@@ -97,32 +112,33 @@ hr, hr2 {
hr2,
.sdpi-heading {
- display: flex;
- flex-basis: 100%;
- align-items: center;
- color: inherit;
- font-size: 9pt;
- margin: 8px 0px;
+ display: flex;
+ flex-basis: 100%;
+ align-items: center;
+ color: inherit;
+ font-size: 9pt;
+ margin: 8px 0px;
}
.sdpi-heading::before,
.sdpi-heading::after {
- content: "";
- flex-grow: 1;
- background: var(--sdpi-background);
- height: 1px;
- font-size: 0px;
- line-height: 0px;
- margin: 0px 16px;
+ content: "";
+ flex-grow: 1;
+ background: var(--sdpi-background);
+ height: 1px;
+ font-size: 0px;
+ line-height: 0px;
+ margin: 0px 16px;
}
hr2 {
height: 2px;
}
-hr, hr2 {
- margin-left:16px;
- margin-right:16px;
+hr,
+hr2 {
+ margin-left: 16px;
+ margin-right: 16px;
}
.sdpi-item-value,
@@ -135,7 +151,10 @@ button {
letter-spacing: var(--sdpi-letterspacing);
}
-
+.sdpi-item-value > :last-of-type,
+.sdpi-item-value:last-child {
+ margin-bottom: 4px;
+}
.win .sdpi-item-value,
.win option,
@@ -169,6 +188,7 @@ meter::-webkit-meter-bar:active {
border-radius: 3px;
background: #222222;
}
+
::-webkit-progress-value:active,
meter::-webkit-meter-optimum-value:active {
background: #99f;
@@ -208,10 +228,10 @@ progress.full {
.tabs {
/**
- * Setting display to flex makes this container lay
- * out its children using flexbox, the exact same
- * as in the above "Stepper input" example.
- */
+ * Setting display to flex makes this container lay
+ * out its children using flexbox, the exact same
+ * as in the above "Stepper input" example.
+ */
display: flex;
border-bottom: 1px solid #D7DBDD;
@@ -229,14 +249,6 @@ progress.full {
border-bottom-color: #4ebbe4;
}
-select {
- -webkit-appearance: none;
- -moz-appearance: none;
- -o-appearance: none;
- appearance: none;
- background: url(caret.svg) no-repeat 97% center;
-}
-
label.sdpi-file-label,
input[type="button"],
input[type="submit"],
@@ -278,7 +290,6 @@ input[type="file"] {
max-width: 220px;
}
-
option {
height: 1.5em;
padding: 4px;
@@ -288,6 +299,7 @@ option {
.sdpi-wrapper {
overflow-x: hidden;
+ height: 100%;
}
.sdpi-item {
@@ -297,26 +309,37 @@ option {
align-items: center;
margin-top: 2px;
max-width: 344px;
+ -webkit-user-drag: none;
}
.sdpi-item:first-child {
- margin-top:1px;
+ margin-top: -1px;
+}
+
+.sdpi-item:first-of-type {
+ margin-top: 2px;
+}
+
+.sdpi-item[type="radio"]:first-of-type,
+.sdpi-item[type="checkbox"]:first-of-type {
+ margin-top: -4px;
}
.sdpi-item:last-child {
margin-bottom: 0px;
}
-.sdpi-item > *:not(.sdpi-item-label):not(meter):not(details) {
+.sdpi-item > *:not(.sdpi-item-label):not(meter):not(details):not(canvas) {
min-height: 26px;
- padding: 0px 4px 0px 4px;
}
.sdpi-item > *:not(.sdpi-item-label.empty):not(meter) {
min-height: 26px;
- padding: 0px 4px 0px 4px;
}
+.sdpi-item > input {
+ padding: 0px 4px;
+}
.sdpi-item-group {
padding: 0 !important;
@@ -380,13 +403,15 @@ table > caption {
text-align: right;
flex: none;
width: 94px;
- padding-right: 4px;
+ padding-right: 5px;
font-weight: 600;
-webkit-user-select: none;
+ line-height: 24px;
+ margin-left: -1px;
}
.win .sdpi-item-label,
-.sdpi-item-label > small{
+.sdpi-item-label > small {
font-weight: normal;
}
@@ -402,7 +427,7 @@ table > caption {
.sdpi-item-value {
flex: 1 0 0;
/* flex-grow: 1;
- flex-shrink: 0; */
+flex-shrink: 0; */
margin-right: 14px;
margin-left: 4px;
justify-content: space-evenly;
@@ -423,8 +448,8 @@ input.sdpi-item-value {
.sdpi-item-value button,
button.sdpi-item-value {
- margin-left: 7px;
- margin-right: 19px;
+ margin-left: 6px;
+ margin-right: 14px;
}
.sdpi-item-value.range {
@@ -437,11 +462,10 @@ ul.sdpi-item-value,
ol.sdpi-item-value,
.sdpi-item-value > dl,
.sdpi-item-value > ul,
-.sdpi-item-value > ol
-{
+.sdpi-item-value > ol {
list-style-type: none;
list-style-position: outside;
- margin-left: -4px;
+ margin-left: -4px;
margin-right: -4px;
padding: 4px;
border: 1px solid var(--sdpi-bordercolor);
@@ -456,12 +480,28 @@ ol.sdpi-item-value,
margin-left: 5px;
margin-right: 12px;
padding: 4px !important;
+ display: flex;
+ flex-direction: column;
+}
+
+.two-items li {
+ display: flex;
+}
+
+.two-items li > *:first-child {
+ flex: 0 0 50%;
+ text-align: left;
+}
+
+.two-items.thirtyseventy li > *:first-child {
+ flex: 0 0 30%;
}
ol.sdpi-item-value,
.sdpi-item-value > ol[listtype="none"] {
list-style-type: none;
}
+
ol.sdpi-item-value[type="decimal"],
.sdpi-item-value > ol[type="decimal"] {
list-style-type: decimal;
@@ -496,15 +536,15 @@ tr:nth-child(even),
.sdpi-item-value > ul > li:nth-child(even),
.sdpi-item-value > ol > li:nth-child(even),
li:nth-child(even) {
- background-color: rgba(0,0,0,.2)
+ background-color: rgba(0, 0, 0, .2)
}
td:hover,
.sdpi-item-value > ul > li:hover:nth-child(even),
.sdpi-item-value > ol > li:hover:nth-child(even),
li:hover:nth-child(even),
-li:hover {
- background-color: rgba(255,255,255,.1);
+li:hover {
+ background-color: rgba(255, 255, 255, .1);
}
td.selected,
@@ -533,12 +573,14 @@ td:last-child {
.sdpi-item-value > select {
margin-right: 13px;
margin-left: 4px;
+ padding: 0px 4px;
}
.sdpi-item-child,
.sdpi-item-group > .sdpi-item > input[type="color"] {
margin-top: 0.4em;
margin-right: 4px;
+ margin-left: 4px;
}
.full,
@@ -548,7 +590,7 @@ td:last-child {
.sdpi-item-child.full,
.sdpi-item-child.full > *,
.full > .sdpi-item-child,
-.full > .sdpi-item-child > *{
+.full > .sdpi-item-child > * {
display: flex;
flex: 1 1 0;
margin-bottom: 4px;
@@ -585,6 +627,11 @@ summary .pointer {
cursor: pointer;
}
+details * {
+ font-size: 12px;
+ font-weight: normal;
+}
+
details.message {
padding: 4px 18px 4px 12px;
}
@@ -598,13 +645,22 @@ details.message summary {
details.message:first-child {
margin-top: 4px;
margin-left: 0;
- padding-left: 106px;
+ padding-left: 102px !important;
+}
+
+details.message > summary:first-of-type {
+ /*line-height: 48px;*/
}
details.message h1 {
- text-align: left;
+ text-align: left;
}
+details:not(.pointer) > summary {
+ list-style: none;
+}
+
+details > summary::-webkit-details-marker
.message > summary::-webkit-details-marker {
display: none;
}
@@ -614,7 +670,7 @@ details.message h1 {
.caution,
.info {
background-repeat: no-repeat;
- background-position: 70px center;
+ background-position: 72px center;
}
.info20 {
@@ -630,8 +686,9 @@ details.message h1 {
}
.sdpi-more-info {
- background-image: linear-gradient(to right, #00000000 0%,#00000040 80%), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpolygon fill='%23999' points='4 7 8 7 8 5 12 8 8 11 8 9 4 9'/%3E%3C/svg%3E%0A");
+ background-image: linear-gradient(to right, #00000000 0%, #00000040 80%), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpolygon fill='%23999' points='4 7 8 7 8 5 12 8 8 11 8 9 4 9'/%3E%3C/svg%3E%0A");
}
+
.caution {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' fill-rule='evenodd' d='M9.03952676,0.746646542 C9.57068894,-0.245797319 10.4285735,-0.25196227 10.9630352,0.746646542 L19.7705903,17.2030214 C20.3017525,18.1954653 19.8777595,19 18.8371387,19 L1.16542323,19 C0.118729947,19 -0.302490098,18.2016302 0.231971607,17.2030214 L9.03952676,0.746646542 Z M10,2.25584053 L1.9601405,17.3478261 L18.04099,17.3478261 L10,2.25584053 Z M10,5.9375 C10.531043,5.9375 10.9615385,6.37373537 10.9615385,6.91185897 L10.9615385,11.6923077 C10.9615385,12.2304313 10.531043,12.6666667 10,12.6666667 C9.46895697,12.6666667 9.03846154,12.2304313 9.03846154,11.6923077 L9.03846154,6.91185897 C9.03846154,6.37373537 9.46895697,5.9375 10,5.9375 Z M10,13.4583333 C10.6372516,13.4583333 11.1538462,13.9818158 11.1538462,14.6275641 L11.1538462,14.6641026 C11.1538462,15.3098509 10.6372516,15.8333333 10,15.8333333 C9.36274837,15.8333333 8.84615385,15.3098509 8.84615385,14.6641026 L8.84615385,14.6275641 C8.84615385,13.9818158 9.36274837,13.4583333 10,13.4583333 Z'/%3E%3C/svg%3E%0A");
}
@@ -646,7 +703,7 @@ details.message h1 {
left: 0px;
right: 0px;
bottom: 0px;
- min-height:16px;
+ min-height: 16px;
padding-right: 16px;
text-align: right;
-webkit-touch-callout: none;
@@ -666,6 +723,27 @@ details.message h1 {
position: fixed;
right: 17px;
bottom: 0px;
+ user-select: none;
+}
+
+
+.sdpi-bottom-bar {
+ display: flex;
+ align-self: right;
+ margin-left: auto;
+ position: fixed;
+ right: 17px;
+ bottom: 0px;
+ user-select: none;
+}
+
+.sdpi-bottom-bar.right {
+ right: 0px;
+}
+
+.sdpi-bottom-bar button {
+ min-height: 20px !important;
+ height: 20px !important;
}
details a {
@@ -675,6 +753,8 @@ details a {
line-height: 24px;
padding-right: 28px;
}
+
+
input:not([type="range"]),
textarea {
-webkit-appearance: none;
@@ -685,16 +765,19 @@ textarea {
border: none;
margin-top: 2px;
margin-bottom: 2px;
+ min-width: 219px;
}
textarea + label {
display: flex;
justify-content: flex-end
}
+
input[type="radio"],
input[type="checkbox"] {
display: none;
}
+
input[type="radio"] + label,
input[type="checkbox"] + label {
font-size: 9pt;
@@ -704,7 +787,7 @@ input[type="checkbox"] + label {
-webkit-user-select: none;
}
-input[type="radio"] + label:after,
+input[type="radio"] + label:after,
input[type="checkbox"] + label:after {
content: " " !important;
}
@@ -718,13 +801,13 @@ input[type="checkbox"] + label:after {
margin-top: 4px;
}
-.sdpi-item[type="checkbox"] .sdpi-item-child,
+.sdpi-item[type="checkbox"] .sdpi-item-child,
.sdpi-item[type="radio"] .sdpi-item-child {
display: inline-block;
}
-.sdpi-item[type="range"] .sdpi-item-value,
-.sdpi-item[type="meter"] .sdpi-item-child,
+.sdpi-item[type="range"] .sdpi-item-value,
+.sdpi-item[type="meter"] .sdpi-item-child,
.sdpi-item[type="progress"] .sdpi-item-child {
display: flex;
}
@@ -733,17 +816,19 @@ input[type="checkbox"] + label:after {
min-height: 26px;
}
-.sdpi-item[type="range"] .sdpi-item-value span,
-.sdpi-item[type="meter"] .sdpi-item-child span,
+.sdpi-item[type="range"] .sdpi-item-value span,
+.sdpi-item[type="meter"] .sdpi-item-child span,
.sdpi-item[type="progress"] .sdpi-item-child span {
margin-top: -2px;
min-width: 8px;
text-align: right;
user-select: none;
cursor: pointer;
+ -webkit-user-select: none;
+ user-select: none;
}
-.sdpi-item[type="range"] .sdpi-item-value span {
+.sdpi-item[type="range"] .sdpi-item-value span {
margin-top: 7px;
text-align: right;
}
@@ -754,14 +839,14 @@ span + input[type="range"] {
}
-.sdpi-item[type="range"] .sdpi-item-value span:first-child,
-.sdpi-item[type="meter"] .sdpi-item-child span:first-child,
+.sdpi-item[type="range"] .sdpi-item-value span:first-child,
+.sdpi-item[type="meter"] .sdpi-item-child span:first-child,
.sdpi-item[type="progress"] .sdpi-item-child span:first-child {
margin-right: 4px;
}
-.sdpi-item[type="range"] .sdpi-item-value span:last-child,
-.sdpi-item[type="meter"] .sdpi-item-child span:last-child,
+.sdpi-item[type="range"] .sdpi-item-value span:last-child,
+.sdpi-item[type="meter"] .sdpi-item-child span:last-child,
.sdpi-item[type="progress"] .sdpi-item-child span:last-child {
margin-left: 4px;
}
@@ -770,7 +855,7 @@ span + input[type="range"] {
transform: rotate(180deg);
}
-.sdpi-item[type="meter"] .sdpi-item-child meter + span:last-child {
+.sdpi-item[type="meter"] .sdpi-item-child meter + span:last-child {
margin-left: -10px;
}
@@ -794,10 +879,13 @@ details > h4 {
legend {
display: none;
}
+
.sdpi-item-value > textarea {
padding: 0px;
- width: 227px;
+ width: 219px;
margin-left: 1px;
+ margin-top: 3px;
+ padding: 4px;
}
input[type="radio"] + label span,
@@ -810,7 +898,7 @@ input[type="checkbox"] + label span {
vertical-align: middle;
background: var(--sdpi-background);
cursor: pointer;
- border: 1px solid rgb(0,0,0,.2);
+ border: 1px solid rgb(0, 0, 0, .2);
}
input[type="radio"] + label span {
@@ -820,10 +908,9 @@ input[type="radio"] + label span {
input[type="radio"]:checked + label span,
input[type="checkbox"]:checked + label span {
background-color: #77f;
- background-image: url(check.svg);
background-repeat: no-repeat;
background-position: center center;
- border: 1px solid rgb(0,0,0,.4);
+ border: 1px solid rgb(0, 0, 0, .4);
}
input[type="radio"]:active:checked + label span,
@@ -833,21 +920,6 @@ input[type="checkbox"]:active + label span {
background-color: #303030;
}
-input[type="radio"]:checked + label span {
- background-image: url(rcheck.svg);
-}
-
-
-/*
-input[type="radio"] + label span {
- background: url(buttons.png) -38px top no-repeat;
-}
-
-input[type="radio"]:checked + label span {
- background: url(buttons.png) -57px top no-repeat;
-}
-*/
-
input[type="range"] {
width: var(--sdpi-width);
height: 30px;
@@ -857,17 +929,18 @@ input[type="range"] {
}
.sdpi-item > input[type="range"] {
- margin-left: 8px;
+ margin-left: 2px;
max-width: var(--sdpi-width);
width: var(--sdpi-width);
padding: 0px;
+ margin-top: 2px;
}
/*
input[type="range"],
input[type="range"]::-webkit-slider-runnable-track,
input[type="range"]::-webkit-slider-thumb {
- -webkit-appearance: none;
+-webkit-appearance: none;
}
*/
@@ -875,7 +948,7 @@ input[type="range"]::-webkit-slider-runnable-track {
height: 5px;
background: #979797;
border-radius: 3px;
- padding:0px !important;
+ padding: 0px !important;
border: 1px solid var(--sdpi-background);
}
@@ -888,9 +961,9 @@ input[type="range"]::-webkit-slider-thumb {
border-radius: 20px;
margin-top: -5px;
border: none;
-
}
-input[type="range" i]{
+
+input[type="range" i] {
margin: 0;
}
@@ -929,7 +1002,7 @@ textarea {
}
textarea {
- width: 221px; /*98%;*/
+ width: 219px; /*98%;*/
height: 96%;
min-height: 6em;
resize: none;
@@ -938,9 +1011,7 @@ textarea {
/* CAROUSEL */
-.sdpi-item[type="carousel"]{
-
-}
+.sdpi-item[type="carousel"] {}
.sdpi-item.card-carousel-wrapper,
.sdpi-item > .card-carousel-wrapper {
@@ -961,9 +1032,11 @@ textarea {
justify-content: center;
width: 278px;
}
+
.card-carousel--overflow-container {
overflow: hidden;
}
+
.card-carousel--nav__left,
.card-carousel--nav__right {
/* display: inline-block; */
@@ -975,28 +1048,35 @@ textarea {
margin: 0 4px;
transition: transform 150ms linear;
}
+
.card-carousel--nav__left[disabled],
.card-carousel--nav__right[disabled] {
opacity: 0.2;
border-color: black;
}
+
.card-carousel--nav__left {
transform: rotate(-135deg);
}
+
.card-carousel--nav__left:active {
transform: rotate(-135deg) scale(0.85);
}
+
.card-carousel--nav__right {
transform: rotate(45deg);
}
+
.card-carousel--nav__right:active {
transform: rotate(45deg) scale(0.85);
}
+
.card-carousel-cards {
display: flex;
transition: transform 150ms ease-out;
transform: translatex(0px);
}
+
.card-carousel-cards .card-carousel--card {
margin: 0 5px;
cursor: pointer;
@@ -1005,12 +1085,15 @@ textarea {
border-radius: 4px;
z-index: 3;
}
+
.xxcard-carousel-cards .card-carousel--card:first-child {
margin-left: 0;
}
+
.xxcard-carousel-cards .card-carousel--card:last-child {
margin-right: 0;
}
+
.card-carousel-cards .card-carousel--card img {
vertical-align: bottom;
border-top-left-radius: 4px;
@@ -1018,9 +1101,11 @@ textarea {
transition: opacity 150ms linear;
width: 60px;
}
+
.card-carousel-cards .card-carousel--card img:hover {
opacity: 0.5;
}
+
.card-carousel-cards .card-carousel--card--footer {
border-top: 0;
max-width: 80px;
@@ -1029,6 +1114,7 @@ textarea {
height: 100%;
flex-direction: column;
}
+
.card-carousel-cards .card-carousel--card--footer p {
padding: 3px 0;
margin: 0;
@@ -1037,6 +1123,7 @@ textarea {
font-weight: 500;
color: #2c3e50;
}
+
.card-carousel-cards .card-carousel--card--footer p:nth-of-type(2) {
font-size: 12px;
font-weight: 300;
@@ -1052,31 +1139,30 @@ h1 {
margin-bottom: 12px;
}
-::-webkit-datetime-edit {
- font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- background: url(elg_calendar_inv.svg) no-repeat left center;
- padding-right: 1em;
- padding-left: 25px;
- background-position: 4px 0px;
- }
-::-webkit-datetime-edit-fields-wrapper {
-
- }
-::-webkit-datetime-edit-text { padding: 0 0.3em; }
-::-webkit-datetime-edit-month-field { }
+::-webkit-datetime-edit-fields-wrapper {}
+
+::-webkit-datetime-edit-text {
+ padding: 0 0.3em;
+}
+
+::-webkit-datetime-edit-month-field {}
+
::-webkit-datetime-edit-day-field {}
+
::-webkit-datetime-edit-year-field {}
-::-webkit-inner-spin-button {
-
+
+::-webkit-inner-spin-button {
+
/* display: none; */
- }
-::-webkit-calendar-picker-indicator {
+}
+
+::-webkit-calendar-picker-indicator {
background: transparent;
- font-size: 17px;
+ font-size: 17px;
}
::-webkit-calendar-picker-indicator:focus {
- background-color: rgba(0,0,0,0.2);
+ background-color: rgba(0, 0, 0, 0.2);
}
input[type="date"] {
@@ -1089,41 +1175,41 @@ input[type="date"] {
}
input::-webkit-datetime-edit {
- -webkit-flex: 1;
- -webkit-user-modify: read-only !important;
- display: inline-block;
- min-width: 0;
- overflow: hidden;
+ -webkit-flex: 1;
+ -webkit-user-modify: read-only !important;
+ display: inline-block;
+ min-width: 0;
+ overflow: hidden;
}
/*
input::-webkit-datetime-edit-fields-wrapper {
- -webkit-user-modify: read-only !important;
- display: inline-block;
- padding: 1px 0;
- white-space: pre;
+-webkit-user-modify: read-only !important;
+display: inline-block;
+padding: 1px 0;
+white-space: pre;
}
*/
-/*
+/*
input[type="date"] {
- background-color: red;
- outline: none;
+background-color: red;
+outline: none;
}
input[type="date"]::-webkit-clear-button {
- font-size: 18px;
- height: 30px;
- position: relative;
+font-size: 18px;
+height: 30px;
+position: relative;
}
input[type="date"]::-webkit-inner-spin-button {
- height: 28px;
+height: 28px;
}
input[type="date"]::-webkit-calendar-picker-indicator {
- font-size: 15px;
+font-size: 15px;
} */
input[type="file"] {
@@ -1138,8 +1224,8 @@ input[type="file"] {
input[type="file"] + span {
display: flex;
- flex: 0 1 auto;
- background-color: #0000ff50;
+ flex: 0 1 auto;
+ background-color: #0000ff50;
}
label.sdpi-file-label {
@@ -1152,7 +1238,7 @@ label.sdpi-file-label {
padding: 0px 4px;
margin: auto;
margin-right: 0px;
- float:right;
+ float: right;
}
.sdpi-file-label > label:active,
@@ -1160,14 +1246,14 @@ label.sdpi-file-label {
label.sdpi-file-label:active,
label.sdpi-file-info:active,
input[type="file"]::-webkit-file-upload-button:active,
-button:active {
+button:active {
background-color: var(--sdpi-color);
- color:#303030;
+ color: #303030;
}
-
-input:required:invalid, input:focus:invalid {
- background: var(--sdpi-background) url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5IiBoZWlnaHQ9IjkiIHZpZXdCb3g9IjAgMCA5IDkiPgogICAgPHBhdGggZmlsbD0iI0Q4RDhEOCIgZD0iTTQuNSwwIEM2Ljk4NTI4MTM3LC00LjU2NTM4NzgyZS0xNiA5LDIuMDE0NzE4NjMgOSw0LjUgQzksNi45ODUyODEzNyA2Ljk4NTI4MTM3LDkgNC41LDkgQzIuMDE0NzE4NjMsOSAzLjA0MzU5MTg4ZS0xNiw2Ljk4NTI4MTM3IDAsNC41IEMtMy4wNDM1OTE4OGUtMTYsMi4wMTQ3MTg2MyAyLjAxNDcxODYzLDQuNTY1Mzg3ODJlLTE2IDQuNSwwIFogTTQsMSBMNCw2IEw1LDYgTDUsMSBMNCwxIFogTTQuNSw4IEM0Ljc3NjE0MjM3LDggNSw3Ljc3NjE0MjM3IDUsNy41IEM1LDcuMjIzODU3NjMgNC43NzYxNDIzNyw3IDQuNSw3IEM0LjIyMzg1NzYzLDcgNCw3LjIyMzg1NzYzIDQsNy41IEM0LDcuNzc2MTQyMzcgNC4yMjM4NTc2Myw4IDQuNSw4IFoiLz4KICA8L3N2Zz4) no-repeat 98% center;
+input:required:invalid,
+input:focus:invalid {
+ background: var(--sdpi-background) url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5IiBoZWlnaHQ9IjkiIHZpZXdCb3g9IjAgMCA5IDkiPgogICAgPHBhdGggZmlsbD0iI0Q4RDhEOCIgZD0iTTQuNSwwIEM2Ljk4NTI4MTM3LC00LjU2NTM4NzgyZS0xNiA5LDIuMDE0NzE4NjMgOSw0LjUgQzksNi45ODUyODEzNyA2Ljk4NTI4MTM3LDkgNC41LDkgQzIuMDE0NzE4NjMsOSAzLjA0MzU5MTg4ZS0xNiw2Ljk4NTI4MTM3IDAsNC41IEMtMy4wNDM1OTE4OGUtMTYsMi4wMTQ3MTg2MyAyLjAxNDcxODYzLDQuNTY1Mzg3ODJlLTE2IDQuNSwwIFogTTQsMSBMNCw2IEw1LDYgTDUsMSBMNCwxIFogTTQuNSw4IEM0Ljc3NjE0MjM3LDggNSw3Ljc3NjE0MjM3IDUsNy41IEM1LDcuMjIzODU3NjMgNC43NzYxNDIzNyw3IDQuNSw3IEM0LjIyMzg1NzYzLDcgNCw3LjIyMzg1NzYzIDQsNy41IEM0LDcuNzc2MTQyMzcgNC4yMjM4NTc2Myw4IDQuNSw4IFoiLz4KICA8L3N2Zz4) no-repeat 98% center;
}
input:required:valid {
@@ -1180,45 +1266,6 @@ input:required:valid {
color: yellow;
}
-[title]:hover {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-[title]:hover::after {
- content: '';
- position: absolute;
- bottom: -1000px;
- left: 8px;
- display: none;
- color: #fff;
- border: 8px solid transparent;
- border-bottom: 8px solid #000;
-}
-[title]:hover::before {
-content: attr(title);
- display: flex;
- justify-content: center;
- align-self: center;
- padding: 6px 12px;
- border-radius: 5px;
- background: rgba(0,0,0,0.8);
- color: var(--sdpi-color);
- font-size: 9pt;
- font-family: sans-serif;
- opacity: 1;
- position: absolute;
- height: auto;
- /* width: 50%;
- left: 35%; */
- text-align: center;
- bottom: 2px;
- z-index: 100;
- box-shadow: 0px 3px 6px rgba(0, 0, 0, .5);
- /* box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); */
-}
-
.sdpi-item-group.file {
width: 232px;
display: flex;
@@ -1247,7 +1294,10 @@ content: attr(title);
}
::-webkit-scrollbar-track {
- -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
+ -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
+ box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
+ margin: 4px;
+ border-radius: 8px;
}
::-webkit-scrollbar-thumb {
@@ -1271,21 +1321,21 @@ a {
input[type=range] {
-webkit-appearance: none;
/* background-color: green; */
- height:6px;
+ height: 6px;
margin-top: 12px;
z-index: 0;
overflow: visible;
}
-/*
+/*
input[type="range"]::-webkit-slider-thumb {
- -webkit-appearance: none;
- background-color: var(--sdpi-color);
- width: 12px;
- height: 12px;
- border-radius: 20px;
- margin-top: -6px;
- border: none;
+-webkit-appearance: none;
+background-color: var(--sdpi-color);
+width: 12px;
+height: 12px;
+border-radius: 20px;
+margin-top: -6px;
+border: none;
} */
:-webkit-slider-thumb {
@@ -1316,6 +1366,12 @@ input[type="range"]::-webkit-slider-thumb {
flex-direction: row;
}
+.rangeLabel {
+ position: absolute;
+ font-weight: normal;
+ margin-top: 24px;
+}
+
:disabled {
color: #993333;
}
@@ -1335,11 +1391,21 @@ select option:disabled {
display: none;
}
-/* debug
-div {
- background-color: rgba(64,128,255,0.2);
+.one-line {
+ min-height: 1.5em;
+}
+
+.two-lines {
+ min-height: 3em;
+}
+
+.three-lines {
+ min-height: 4.5em;
+}
+
+.four-lines {
+ min-height: 6em;
}
-*/
.min80 > .sdpi-item-child {
min-width: 80px;
@@ -1404,25 +1470,58 @@ div {
}
.hidden {
- display: none;
+ display: none !important;
}
+.icon-help,
+.icon-help-line,
+.icon-help-fill,
+.icon-help-inv,
.icon-brighter,
.icon-darker,
.icon-warmer,
.icon-cooler {
- margin-top: 5px !important;
min-width: 20px;
width: 20px;
background-repeat: no-repeat;
+ opacity: 1;
+}
+
+.icon-help:active,
+.icon-help-line:active,
+.icon-help-fill:active,
+.icon-help-inv:active,
+.icon-brighter:active,
+.icon-darker:active,
+.icon-warmer:active,
+.icon-cooler:active {
+ opacity: 0.5;
+}
+
+.icon-brighter,
+.icon-darker,
+.icon-warmer,
+.icon-cooler {
+ margin-top: 5px !important;
+}
+
+.icon-help,
+.icon-help-line,
+.icon-help-fill,
+.icon-help-inv {
+ cursor: pointer;
+ margin: 0px;
+ margin-left: 4px;
}
.icon-brighter {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Ccircle cx='10' cy='10' r='4'/%3E%3Cpath d='M14.8532861,7.77530426 C14.7173255,7.4682615 14.5540843,7.17599221 14.3666368,6.90157083 L16.6782032,5.5669873 L17.1782032,6.4330127 L14.8532861,7.77530426 Z M10.5,4.5414007 C10.2777625,4.51407201 10.051423,4.5 9.82179677,4.5 C9.71377555,4.5 9.60648167,4.50311409 9.5,4.50925739 L9.5,2 L10.5,2 L10.5,4.5414007 Z M5.38028092,6.75545367 C5.18389364,7.02383457 5.01124349,7.31068015 4.86542112,7.61289977 L2.82179677,6.4330127 L3.32179677,5.5669873 L5.38028092,6.75545367 Z M4.86542112,12.3871002 C5.01124349,12.6893198 5.18389364,12.9761654 5.38028092,13.2445463 L3.32179677,14.4330127 L2.82179677,13.5669873 L4.86542112,12.3871002 Z M9.5,15.4907426 C9.60648167,15.4968859 9.71377555,15.5 9.82179677,15.5 C10.051423,15.5 10.2777625,15.485928 10.5,15.4585993 L10.5,18 L9.5,18 L9.5,15.4907426 Z M14.3666368,13.0984292 C14.5540843,12.8240078 14.7173255,12.5317385 14.8532861,12.2246957 L17.1782032,13.5669873 L16.6782032,14.4330127 L14.3666368,13.0984292 Z'/%3E%3C/g%3E%3C/svg%3E");
}
+
.icon-darker {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M10 14C7.790861 14 6 12.209139 6 10 6 7.790861 7.790861 6 10 6 12.209139 6 14 7.790861 14 10 14 12.209139 12.209139 14 10 14zM10 13C11.6568542 13 13 11.6568542 13 10 13 8.34314575 11.6568542 7 10 7 8.34314575 7 7 8.34314575 7 10 7 11.6568542 8.34314575 13 10 13zM14.8532861 7.77530426C14.7173255 7.4682615 14.5540843 7.17599221 14.3666368 6.90157083L16.6782032 5.5669873 17.1782032 6.4330127 14.8532861 7.77530426zM10.5 4.5414007C10.2777625 4.51407201 10.051423 4.5 9.82179677 4.5 9.71377555 4.5 9.60648167 4.50311409 9.5 4.50925739L9.5 2 10.5 2 10.5 4.5414007zM5.38028092 6.75545367C5.18389364 7.02383457 5.01124349 7.31068015 4.86542112 7.61289977L2.82179677 6.4330127 3.32179677 5.5669873 5.38028092 6.75545367zM4.86542112 12.3871002C5.01124349 12.6893198 5.18389364 12.9761654 5.38028092 13.2445463L3.32179677 14.4330127 2.82179677 13.5669873 4.86542112 12.3871002zM9.5 15.4907426C9.60648167 15.4968859 9.71377555 15.5 9.82179677 15.5 10.051423 15.5 10.2777625 15.485928 10.5 15.4585993L10.5 18 9.5 18 9.5 15.4907426zM14.3666368 13.0984292C14.5540843 12.8240078 14.7173255 12.5317385 14.8532861 12.2246957L17.1782032 13.5669873 16.6782032 14.4330127 14.3666368 13.0984292z'/%3E%3C/g%3E%3C/svg%3E");
}
+
.icon-warmer {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M12.3247275 11.4890349C12.0406216 11.0007637 11.6761954 10.5649925 11.2495475 10.1998198 11.0890394 9.83238991 11 9.42659309 11 9 11 7.34314575 12.3431458 6 14 6 15.6568542 6 17 7.34314575 17 9 17 10.6568542 15.6568542 12 14 12 13.3795687 12 12.8031265 11.8116603 12.3247275 11.4890349zM17.6232392 11.6692284C17.8205899 11.4017892 17.9890383 11.1117186 18.123974 10.8036272L20.3121778 12.0669873 19.8121778 12.9330127 17.6232392 11.6692284zM18.123974 7.19637279C17.9890383 6.88828142 17.8205899 6.5982108 17.6232392 6.33077158L19.8121778 5.0669873 20.3121778 5.9330127 18.123974 7.19637279zM14.5 4.52746439C14.3358331 4.50931666 14.1690045 4.5 14 4.5 13.8309955 4.5 13.6641669 4.50931666 13.5 4.52746439L13.5 2 14.5 2 14.5 4.52746439zM13.5 13.4725356C13.6641669 13.4906833 13.8309955 13.5 14 13.5 14.1690045 13.5 14.3358331 13.4906833 14.5 13.4725356L14.5 16 13.5 16 13.5 13.4725356zM14 11C15.1045695 11 16 10.1045695 16 9 16 7.8954305 15.1045695 7 14 7 12.8954305 7 12 7.8954305 12 9 12 10.1045695 12.8954305 11 14 11zM9.5 11C10.6651924 11.4118364 11.5 12.5 11.5 14 11.5 16 10 17.5 8 17.5 6 17.5 4.5 16 4.5 14 4.5 12.6937812 5 11.5 6.5 11L6.5 7 9.5 7 9.5 11z'/%3E%3Cpath d='M12,14 C12,16.209139 10.209139,18 8,18 C5.790861,18 4,16.209139 4,14 C4,12.5194353 4.80439726,11.2267476 6,10.5351288 L6,4 C6,2.8954305 6.8954305,2 8,2 C9.1045695,2 10,2.8954305 10,4 L10,10.5351288 C11.1956027,11.2267476 12,12.5194353 12,14 Z M11,14 C11,12.6937812 10.1651924,11.5825421 9,11.1707057 L9,4 C9,3.44771525 8.55228475,3 8,3 C7.44771525,3 7,3.44771525 7,4 L7,11.1707057 C5.83480763,11.5825421 5,12.6937812 5,14 C5,15.6568542 6.34314575,17 8,17 C9.65685425,17 11,15.6568542 11,14 Z'/%3E%3C/g%3E%3C/svg%3E");
}
@@ -1431,85 +1530,103 @@ div {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M10.4004569 11.6239517C10.0554735 10.9863849 9.57597206 10.4322632 9 9.99963381L9 9.7450467 9.53471338 9.7450467 10.8155381 8.46422201C10.7766941 8.39376637 10.7419749 8.32071759 10.7117062 8.2454012L9 8.2454012 9 6.96057868 10.6417702 6.96057868C10.6677696 6.86753378 10.7003289 6.77722682 10.7389179 6.69018783L9.44918707 5.40045694 9 5.40045694 9 4.34532219 9.32816127 4.34532219 9.34532219 2.91912025 10.4004569 2.91912025 10.4004569 4.53471338 11.6098599 5.74411634C11.7208059 5.68343597 11.8381332 5.63296451 11.9605787 5.59396526L11.9605787 3.8884898 10.8181818 2.74609294 11.5642748 2 12.5727518 3.00847706 13.5812289 2 14.3273218 2.74609294 13.2454012 3.82801356 13.2454012 5.61756719C13.3449693 5.65339299 13.4408747 5.69689391 13.5324038 5.74735625L14.7450467 4.53471338 14.7450467 2.91912025 15.8001815 2.91912025 15.8001815 4.34532219 17.2263834 4.34532219 17.2263834 5.40045694 15.6963166 5.40045694 14.4002441 6.69652946C14.437611 6.78161093 14.4692249 6.86979146 14.4945934 6.96057868L16.2570138 6.96057868 17.3994107 5.81818182 18.1455036 6.56427476 17.1370266 7.57275182 18.1455036 8.58122888 17.3994107 9.32732182 16.3174901 8.2454012 14.4246574 8.2454012C14.3952328 8.31861737 14.3616024 8.38969062 14.3240655 8.45832192L15.6107903 9.7450467 17.2263834 9.7450467 17.2263834 10.8001815 15.8001815 10.8001815 15.8001815 12.2263834 14.7450467 12.2263834 14.7450467 10.6963166 13.377994 9.32926387C13.3345872 9.34850842 13.2903677 9.36625331 13.2454012 9.38243281L13.2454012 11.3174901 14.3273218 12.3994107 13.5812289 13.1455036 12.5848864 12.1491612 11.5642748 13.1455036 10.8181818 12.3994107 11.9605787 11.2570138 11.9605787 9.40603474C11.8936938 9.38473169 11.828336 9.36000556 11.7647113 9.33206224L10.4004569 10.6963166 10.4004569 11.6239517zM12.75 8.5C13.3022847 8.5 13.75 8.05228475 13.75 7.5 13.75 6.94771525 13.3022847 6.5 12.75 6.5 12.1977153 6.5 11.75 6.94771525 11.75 7.5 11.75 8.05228475 12.1977153 8.5 12.75 8.5zM9.5 14C8.5 16.3333333 7.33333333 17.5 6 17.5 4.66666667 17.5 3.5 16.3333333 2.5 14L9.5 14z'/%3E%3Cpath d='M10,14 C10,16.209139 8.209139,18 6,18 C3.790861,18 2,16.209139 2,14 C2,12.5194353 2.80439726,11.2267476 4,10.5351288 L4,4 C4,2.8954305 4.8954305,2 6,2 C7.1045695,2 8,2.8954305 8,4 L8,10.5351288 C9.19560274,11.2267476 10,12.5194353 10,14 Z M9,14 C9,12.6937812 8.16519237,11.5825421 7,11.1707057 L7,4 C7,3.44771525 6.55228475,3 6,3 C5.44771525,3 5,3.44771525 5,4 L5,11.1707057 C3.83480763,11.5825421 3,12.6937812 3,14 C3,15.6568542 4.34314575,17 6,17 C7.65685425,17 9,15.6568542 9,14 Z'/%3E%3C/g%3E%3C/svg%3E");
}
-/**
-input[type=range].vVertical {
- -webkit-appearance: none;
- background-color: green;
- margin-left: -60px;
- width: 100px;
- height:6px;
- margin-top: 0px;
- transform:rotate(90deg);
- z-index: 0;
- overflow: visible;
+.icon-help {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cpath fill='%23999' d='M11.292 12.516l.022 1.782H9.07v-1.804c0-1.98 1.276-2.574 2.662-3.278h-.022c.814-.44 1.65-.88 1.694-2.2.044-1.386-1.122-2.728-3.234-2.728-1.518 0-2.662.902-3.366 2.354L5 5.608C5.946 3.584 7.662 2 10.17 2c3.564 0 5.632 2.442 5.588 5.06-.066 2.618-1.716 3.41-3.102 4.158-.704.374-1.364.682-1.364 1.298zm-1.122 2.442c.858 0 1.452.594 1.452 1.452 0 .682-.594 1.408-1.452 1.408-.77 0-1.386-.726-1.386-1.408 0-.858.616-1.452 1.386-1.452z'/%3E%3C/svg%3E");
}
-input[type=range].vHorizon {
- -webkit-appearance: none;
- background-color: pink;
- height: 10px;
- width:200px;
-
+.icon-help-line {
+ background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-1a9 9 0 1 0 0-18 9 9 0 0 0 0 18z'/%3E%3Cpath d='M10.848 12.307l.02 1.578H8.784v-1.597c0-1.753 1.186-2.278 2.474-2.901h-.02c.756-.39 1.533-.78 1.574-1.948.041-1.226-1.043-2.414-3.006-2.414-1.41 0-2.474.798-3.128 2.083L5 6.193C5.88 4.402 7.474 3 9.805 3 13.118 3 15.04 5.161 15 7.478c-.061 2.318-1.595 3.019-2.883 3.68-.654.332-1.268.604-1.268 1.15zM9.805 14.47c.798 0 1.35.525 1.35 1.285 0 .603-.552 1.246-1.35 1.246-.715 0-1.288-.643-1.288-1.246 0-.76.573-1.285 1.288-1.285z' fill-rule='nonzero'/%3E%3C/g%3E%3C/svg%3E");
}
-.test2 {
- background-color: #00ff0020;
- display: flex;
+.icon-help-fill {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Ccircle cx='10' cy='10' r='10' fill='%23999'/%3E%3Cpath fill='%23FFF' fill-rule='nonzero' d='M8.368 7.189H5C5 3.5 7.668 2 10.292 2 13.966 2 16 4.076 16 7.012c0 3.754-3.849 3.136-3.849 5.211v1.656H8.455v-1.832c0-2.164 1.4-2.893 2.778-3.6.437-.242 1.006-.574 1.006-1.236 0-2.208-3.871-2.142-3.871-.022zM10.25 18a1.75 1.75 0 1 1 0-3.5 1.75 1.75 0 0 1 0 3.5z'/%3E%3C/g%3E%3C/svg%3E");
}
-
-.vertical.sdpi-item[type="range"] .sdpi-item-value {
- display: block;
+.icon-help-inv {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cpath fill='%23999' fill-rule='evenodd' d='M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zM8.368 7.189c0-2.12 3.87-2.186 3.87.022 0 .662-.568.994-1.005 1.236-1.378.707-2.778 1.436-2.778 3.6v1.832h3.696v-1.656c0-2.075 3.849-1.457 3.849-5.21C16 4.075 13.966 2 10.292 2 7.668 2 5 3.501 5 7.189h3.368zM10.25 18a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5z'/%3E%3C/svg%3E");
}
-
-.vertical.sdpi-item:first-child,
-.vertical {
- margin-top: 12px;
- margin-bottom: 16px;
+.kelvin::after {
+ content: "K";
}
-.vertical > .sdpi-item-value {
- margin-right: 16px;
+
+.mired::after {
+ content: " Mired";
}
-.vertical .sdpi-item-group {
- width: 100%;
- display: flex;
- justify-content: space-evenly;
+.percent::after {
+ content: "%";
}
-.vertical input[type=range] {
- height: 100px;
- width: 21px;
- -webkit-appearance: slider-vertical;
- display: flex;
- flex-flow: column;
+.sdpi-item-value + .icon-cooler,
+.sdpi-item-value + .icon-warmer {
+ margin-left: 0px !important;
+ margin-top: 15px !important;
}
-.vertical input[type="range"]::-webkit-slider-runnable-track {
- height: auto;
- width: 5px;
+/**
+CONTROL-CENTER STYLES
+*/
+input[type="range"].colorbrightness::-webkit-slider-runnable-track,
+input[type="range"].colortemperature::-webkit-slider-runnable-track {
+ height: 8px;
+ background: #979797;
+ border-radius: 4px;
+ background-image: linear-gradient(to right, #94d0ec, #ffb165);
}
-.vertical input[type="range"]::-webkit-slider-thumb {
- margin-top: 0px;
- margin-left: -6px;
+input[type="range"].colorbrightness::-webkit-slider-runnable-track {
+ background-color: #efefef;
+ background-image: linear-gradient(to right, black, rgba(0, 0, 0, 0));
}
-.vertical .sdpi-item-value {
- flex-flow: column;
- align-items: flex-start;
+
+input[type="range"].colorbrightness::-webkit-slider-thumb,
+input[type="range"].colortemperature::-webkit-slider-thumb {
+ width: 16px;
+ height: 16px;
+ border-radius: 20px;
+ margin-top: -5px;
+ background-color: #86c6e8;
+ box-shadow: 0px 0px 1px #000000;
+ border: 1px solid #d8d8d8;
}
-.vertical.sdpi-item[type="range"] .sdpi-item-value {
- align-items: center;
- margin-right: 16px;
+.sdpi-info-label {
+ display: inline-block;
+ user-select: none;
+ position: absolute;
+ height: 15px;
+ width: auto;
text-align: center;
+ border-radius: 4px;
+ min-width: 44px;
+ max-width: 80px;
+ background: white;
+ font-size: 11px;
+ color: black;
+ z-index: 1000;
+ box-shadow: 0px 0px 12px rgba(0, 0, 0, .8);
+ padding: 2px;
+
}
-.vertical.sdpi-item[type="range"] .sdpi-item-value span,
-.vertical input[type="range"] .sdpi-item-value span {
- text-align: center;
- margin: 4px 0px;
+.sdpi-info-label.hidden {
+ opacity: 0;
+ transition: opacity 0.25s linear;
}
-*/
\ No newline at end of file
+
+.sdpi-info-label.shown {
+ position: absolute;
+ opacity: 1;
+ transition: opacity 0.25s ease-out;
+}
+
+/* adding some styles here that override sdpi things so we can use this as notes for sdpi updates*/
+select {
+ min-width: 0px;
+
+ /* this is a clunky fix for using background image as select arrow with long text options */
+ -webkit-appearance: media-slider;
+ text-overflow: ellipsis;
+}
\ No newline at end of file
diff --git a/Source/pi/src/main.tsx b/Source/pi/src/main.tsx
new file mode 100644
index 0000000..3d7150d
--- /dev/null
+++ b/Source/pi/src/main.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.tsx'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/Source/pi/src/sd.tsx b/Source/pi/src/sd.tsx
new file mode 100644
index 0000000..ada86e3
--- /dev/null
+++ b/Source/pi/src/sd.tsx
@@ -0,0 +1,146 @@
+import type { inInfo, ActionInfo } from './types/streamdeck'
+
+export type ISD = {
+ // Properties
+ websocket: WebSocket
+ uuid: string
+ registerEventName: string
+ Info: inInfo
+ actionInfo: ActionInfo
+ runningApps: string[]
+ isQT: boolean
+
+ // Send functions
+ sendValueToPlugin: (action: string, context: string, payload: T) => void
+ setSettings: (payload: T) => void
+ sendPayloadToPlugin: (payload: T) => void // any?
+ openWebsite: (url: string) => void
+
+ // Callbacks
+ callbacks: {
+ OnDidReceiveSettings: (f: (settings: T) => void) => void
+ OnDidReceiveGlobalSettings: (f: (settings: T) => void) => void
+ OnSendToPropertyInspector: (f: (payload: T) => void) => void
+ }
+
+ // TODO:
+ // logMessage
+ // getSettings
+ // getGlobalSettings
+}
+
+export class SD implements ISD {
+ websocket: WebSocket
+ uuid: string
+ registerEventName: string
+ Info: inInfo
+ actionInfo: ActionInfo
+ runningApps: string[]
+ isQT: boolean
+
+ callbacks: {
+ onOpen: () => void
+ OnDidReceiveSettings: (payload: unknown) => void
+ OnDidReceiveGlobalSettings: (payload: unknown) => void
+ OnSendToPropertyInspector: (payload: unknown) => void
+ }
+
+ constructor(
+ inPort: number,
+ inPropertyInspectorUUID: string,
+ inRegisterEvent: string,
+ inInfo: string,
+ inActionInfo: string,
+ // callbacks
+ callbacks: {
+ onOpen: () => void
+ OnDidReceiveSettings: (settings: unknown) => void
+ OnDidReceiveGlobalSettings: (settings: unknown) => void
+ OnSendToPropertyInspector: (settings: unknown) => void
+ },
+ ) {
+ this.websocket = new WebSocket(`ws://127.0.0.1:${inPort}`)
+ this.uuid = inPropertyInspectorUUID
+ this.registerEventName = inRegisterEvent
+ this.Info = JSON.parse(inInfo)
+ this.actionInfo = JSON.parse(inActionInfo)
+ this.runningApps = []
+ this.isQT = navigator.appVersion.includes('QtWebEngine') // TODO: fix
+ this.callbacks = callbacks
+
+ // Register websocket callbacks
+ this.websocket.onopen = this.onOpen
+ this.websocket.onmessage = this.onMessage
+
+ // Call the plugin to get the current settings
+ this.callbacks.OnDidReceiveSettings(this.actionInfo.payload.settings)
+ }
+
+ sendValueToPlugin: (param: string, value: string) => void = (param, value) => {
+ const json = {
+ action: this.actionInfo.action,
+ event: 'sendToPlugin',
+ context: this.uuid,
+ payload: {
+ [param]: value,
+ },
+ }
+ console.log('sendValueToPlugin', json)
+ this.websocket.send(JSON.stringify(json))
+ }
+
+ setSettings: (payload: T) => void = (payload) => {
+ const json = {
+ event: 'setSettings',
+ context: this.uuid,
+ payload: payload,
+ }
+ this.websocket.send(JSON.stringify(json))
+ }
+
+ sendPayloadToPlugin: (payload: T) => void = (payload) => {
+ const json = {
+ action: this.actionInfo.action,
+ event: 'sendToPlugin',
+ context: this.uuid,
+ payload: payload,
+ }
+ this.websocket.send(JSON.stringify(json))
+ }
+
+ openWebsite: (url: string) => void = (url) => {
+ const json = {
+ event: 'openUrl',
+ payload: {
+ url: url,
+ },
+ }
+ this.websocket.send(JSON.stringify(json))
+ }
+
+ protected onOpen: () => void = () => {
+ const json = {
+ event: this.registerEventName,
+ uuid: this.uuid,
+ }
+ this.websocket.send(JSON.stringify(json))
+
+ // Notify the plugin that we are connected
+ this.sendValueToPlugin('property_inspector', 'propertyInspectorConnected')
+
+ this.callbacks.onOpen()
+ }
+
+ protected onMessage: (event: MessageEvent) => void = (event) => {
+ const json = JSON.parse(event.data)
+ if (json.event === 'didReceiveSettings') {
+ this.callbacks.OnDidReceiveSettings(json.payload)
+ }
+ if (json.event === 'didReceiveGlobalSettings') {
+ this.callbacks.OnDidReceiveGlobalSettings(json.payload)
+ }
+ if (json.event === 'sendToPropertyInspector') {
+ this.callbacks.OnSendToPropertyInspector(json.payload)
+ }
+ }
+}
diff --git a/Source/pi/src/types/streamdeck.ts b/Source/pi/src/types/streamdeck.ts
new file mode 100644
index 0000000..119564a
--- /dev/null
+++ b/Source/pi/src/types/streamdeck.ts
@@ -0,0 +1,78 @@
+export type input = {
+ key: string
+ name: string
+ number: number
+}
+
+// StreamDeck
+export interface inInfo {
+ application: Application
+ plugin: Plugin
+ devicePixelRatio: number
+ colors: Colors
+ devices: Device[]
+}
+
+export interface Application {
+ font: string
+ language: string
+ platform: string
+ platformVersion: string
+ version: string
+}
+
+export interface Plugin {
+ uuid: string
+ version: string
+}
+
+export interface Colors {
+ buttonPressedBackgroundColor: string
+ buttonPressedBorderColor: string
+ buttonPressedTextColor: string
+ disabledColor: string
+ highlightColor: string
+ mouseDownColor: string
+}
+
+export interface Device {
+ id: string
+ name: string
+ size: Size
+ type: number
+}
+
+export interface Size {
+ columns: number
+ rows: number
+}
+
+export interface ActionInfo {
+ action: string
+ context: string
+ device: string
+ payload: Payload
+}
+
+export interface Payload {
+ settings: T
+ coordinates: Coordinates
+}
+
+export interface Coordinates {
+ column: number
+ row: number
+}
+
+export interface SendToPropertyInspector {
+ event: string
+ payload: T
+}
+
+export interface SendInputs {
+ inputs: DestinationToInputs
+}
+
+export interface DestinationToInputs {
+ [key: string]: input[]
+}
diff --git a/Source/pi/src/vite-env.d.ts b/Source/pi/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/Source/pi/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/Source/pi/tailwind.config.js b/Source/pi/tailwind.config.js
new file mode 100644
index 0000000..7cb7e37
--- /dev/null
+++ b/Source/pi/tailwind.config.js
@@ -0,0 +1,77 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ darkMode: ["class"],
+ content: [
+ './pages/**/*.{ts,tsx}',
+ './components/**/*.{ts,tsx}',
+ './app/**/*.{ts,tsx}',
+ './src/**/*.{ts,tsx}',
+ ],
+ prefix: "",
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: { height: "0" },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: "0" },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+}
\ No newline at end of file
diff --git a/Source/pi/tsconfig.json b/Source/pi/tsconfig.json
new file mode 100644
index 0000000..de3bc50
--- /dev/null
+++ b/Source/pi/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }],
+}
diff --git a/Source/pi/tsconfig.node.json b/Source/pi/tsconfig.node.json
new file mode 100644
index 0000000..97ede7e
--- /dev/null
+++ b/Source/pi/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/Source/pi/vite.config.ts b/Source/pi/vite.config.ts
new file mode 100644
index 0000000..8a82ca8
--- /dev/null
+++ b/Source/pi/vite.config.ts
@@ -0,0 +1,17 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react-swc'
+import { viteSingleFile } from 'vite-plugin-singlefile'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react(), viteSingleFile()],
+ build: {
+ minify: false,
+ target: false,
+ rollupOptions: {
+ output: {
+ manualChunks: undefined,
+ },
+ },
+ },
+})
diff --git a/Taskfile.yml b/Taskfile.yml
new file mode 100644
index 0000000..ca8a700
--- /dev/null
+++ b/Taskfile.yml
@@ -0,0 +1,66 @@
+version: '3'
+
+
+includes:
+ vars:
+ taskfile: TaskfileVars.yml
+ flatten: true
+ build:
+ taskfile: ./Taskfile_{{OS}}.yml
+ flatten: true
+
+tasks:
+ test:
+ dir: Source/code
+ cmds:
+ - go test -v ./...
+ vet:
+ dir: Source/code
+ cmds:
+ - go vet ./...
+
+ setup-pi:
+ dir: Source/pi
+ cmds:
+ - npm i
+ setup-server:
+ dir: Source/code
+ cmds:
+ - go mod download
+ setup:
+ deps:
+ - setup-pi
+ - setup-server
+
+ build-pi:
+ dir: Source/pi
+ cmds:
+ - npm run build
+ build-server-windows:
+ dir: Source/code/cmd
+ cmds:
+ - go build -o {{.AppName}}/vmix_go.exe .
+ env:
+ GOOS: windows
+ build-server-darwin:
+ dir: Source/code/cmd
+ cmds:
+ - go build -o {{.AppName}}/vmix_go .
+ env:
+ GOOS: darwin
+ build-server:
+ deps:
+ - build-server-windows
+ - build-server-darwin
+ build:
+ deps:
+ - clean
+ - build-pi
+ - build-server
+
+ clean:
+ dir: Source
+ cmds:
+ - rm -rf {{.ReleaseDir}}
+ - rm -rf {{.AppName}}
+ - mkdir {{.AppName}}
\ No newline at end of file
diff --git a/TaskfileVars.yml b/TaskfileVars.yml
new file mode 100644
index 0000000..d7dfafd
--- /dev/null
+++ b/TaskfileVars.yml
@@ -0,0 +1,7 @@
+version: '3'
+
+vars:
+ AppName: dev.flowingspdg.vmix.sdPlugin
+ CodeDir: Source/code
+ PiDir: Source/pi
+ ReleaseDir: Release
\ No newline at end of file
diff --git a/Taskfile_darwin.yml b/Taskfile_darwin.yml
new file mode 100644
index 0000000..17472ab
--- /dev/null
+++ b/Taskfile_darwin.yml
@@ -0,0 +1,13 @@
+version: '3'
+
+includes:
+ vars:
+ taskfile: TaskfileVars.yml
+ flatten: true
+
+tasks:
+ release:
+ deps:
+ - build
+ cmds:
+ - ./DistributionTool -b -i {{.AppName}} -o {{.ReleaseDir}}
\ No newline at end of file
diff --git a/Taskfile_windows.yml b/Taskfile_windows.yml
new file mode 100644
index 0000000..224ba1d
--- /dev/null
+++ b/Taskfile_windows.yml
@@ -0,0 +1,13 @@
+version: '3'
+
+includes:
+ vars:
+ taskfile: TaskfileVars.yml
+ flatten: true
+
+tasks:
+ release:
+ deps:
+ - build
+ cmds:
+ - .\\DistributionTool.exe -b -i {{.AppName}} -o {{.ReleaseDir}}
\ No newline at end of file
diff --git a/go.mod b/go.mod
deleted file mode 100644
index a01a20b..0000000
--- a/go.mod
+++ /dev/null
@@ -1,13 +0,0 @@
-module github.com/FlowingSPDG/streamdeck-vmix-plugin
-
-go 1.19
-
-require (
- github.com/FlowingSPDG/streamdeck v0.0.0-20221216130808-df1199768e06
- github.com/FlowingSPDG/vmix-go v0.2.3
-)
-
-require (
- github.com/gorilla/websocket v1.5.0 // indirect
- golang.org/x/sync v0.1.0 // indirect
-)
diff --git a/go.sum b/go.sum
deleted file mode 100644
index 74b027a..0000000
--- a/go.sum
+++ /dev/null
@@ -1,38 +0,0 @@
-github.com/FlowingSPDG/streamdeck v0.0.0-20210429012723-f80010a5bcb9 h1:XYgvmBMB5p+kq2vZ6nG3vcHw3YjZAX+RSK24rJRp2dA=
-github.com/FlowingSPDG/streamdeck v0.0.0-20210429012723-f80010a5bcb9/go.mod h1:NbG8TQq6KojwcOwtr4M0AnxOHf+u1NVse4qrhdeuB/c=
-github.com/FlowingSPDG/streamdeck v0.0.0-20221216130808-df1199768e06 h1:1Rc8NBLDek11I9Pb2GBtoBrzIqcm3eHr1p+8/O7Yd5c=
-github.com/FlowingSPDG/streamdeck v0.0.0-20221216130808-df1199768e06/go.mod h1:/3QMNCoMlb25Lcc2GIoFEzijCcvggilMxTDk7EiuQps=
-github.com/FlowingSPDG/vmix-go v0.2.3 h1:1888/CV3Nn44O1F0wKBwfZe3Zg/w8goV10KG6UAT51g=
-github.com/FlowingSPDG/vmix-go v0.2.3/go.mod h1:7wd7yCZyLzNyJ8sfwGYTHRYPDdQNUeaKkre9SDk2g6c=
-github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
-github.com/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
-github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
-github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03/go.mod h1:Z9+Ul5bCbBKnbCvdOWbLqTHhJiYV414CURZJba6L8qA=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=