CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue-facing-decorator

Vue typescript class and decorator based component system with support for ES class inheritance and Vue 3 composition API integration.

Pending
Overview
Eval results
Files

property-decorators.mddocs/

Property Decorators

Decorators for reactive properties, props, template references, and data binding in Vue components.

Capabilities

Setup Decorator

Decorator for setup functions that return reactive data, integrating with Vue 3's Composition API.

/**
 * Decorator for setup functions that return reactive data
 * @param setupFunction - Function that returns reactive data or Promise of reactive data
 * @returns Property decorator
 */
function Setup(setupFunction: OptionSetupFunction): PropertyDecorator;

type OptionSetupFunction = (
  props: Readonly<any>, 
  ctx: SetupContext<any>
) => any | Promise<any>;

interface SetupConfig {
  setupFunction: OptionSetupFunction;
}

Usage Examples:

import { Component, Setup } from "vue-facing-decorator";
import { ref, computed, reactive } from "vue";

@Component
class SetupComponent {
  // Simple reactive reference
  @Setup(() => ref("initial value"))
  message!: string;

  // Reactive object
  @Setup(() => reactive({ count: 0, items: [] }))
  state!: { count: number; items: any[] };

  // Computed property
  @Setup(() => computed(() => `Count: ${this.state.count}`))
  displayText!: string;

  // Async setup
  @Setup(async () => {
    const data = await fetch('/api/data');
    return ref(await data.json());
  })
  asyncData!: any;

  // Setup with context
  @Setup((props, { emit, slots, attrs }) => {
    const handleClick = () => emit('clicked');
    return ref({ handleClick });
  })
  handlers!: { handleClick: () => void };
}

Ref Decorator

Decorator for template references ($refs) with optional custom key names.

/**
 * Decorator for template references
 * @param key - Optional custom ref key name, defaults to property name
 * @returns Property decorator
 */
function Ref(key?: string): PropertyDecorator;

type RefConfig = null | string;

Usage Examples:

import { Component, Ref } from "vue-facing-decorator";

@Component({
  template: `
    <div>
      <input ref="inputElement" />
      <button ref="submitBtn">Submit</button>
      <div ref="customKey">Custom</div>
    </div>
  `
})
class RefComponent {
  // Basic ref - uses property name as ref key
  @Ref()
  inputElement!: HTMLInputElement;

  // Basic ref with different property name
  @Ref()
  submitBtn!: HTMLButtonElement;

  // Custom ref key
  @Ref("customKey")
  myDiv!: HTMLDivElement;

  mounted() {
    // Access refs after component is mounted
    this.inputElement.focus();
    this.submitBtn.addEventListener('click', this.handleSubmit);
    this.myDiv.style.color = 'blue';
  }

  handleSubmit() {
    console.log('Input value:', this.inputElement.value);
  }
}

Prop Decorator

Decorator for component props with comprehensive validation and configuration options.

/**
 * Decorator for component props with validation
 * @param config - Optional prop configuration
 * @returns Property decorator
 */
function Prop(config?: PropsConfig): PropertyDecorator;

interface PropsConfig {
  type?: any;
  required?: boolean;
  default?: any;
  validator?(value: any): boolean;
}

Usage Examples:

import { Component, Prop } from "vue-facing-decorator";

@Component
class PropComponent {
  // Basic prop
  @Prop()
  message!: string;

  // Required prop with type
  @Prop({ type: String, required: true })
  title!: string;

  // Prop with default value
  @Prop({ type: Number, default: 0 })
  count!: number;

  // Prop with validator
  @Prop({
    type: String,
    validator: (value: string) => ['small', 'medium', 'large'].includes(value)
  })
  size!: 'small' | 'medium' | 'large';

  // Complex prop types
  @Prop({ type: Array, default: () => [] })
  items!: any[];

  @Prop({ type: Object, default: () => ({}) })
  config!: Record<string, any>;

  // Custom prop type
  @Prop({
    type: [String, Number],
    validator: (value) => {
      return (typeof value === 'string' && value.length > 0) ||
             (typeof value === 'number' && value > 0);
    }
  })
  id!: string | number;
}

VModel Decorator

Decorator for v-model binding with two-way data flow support.

/**
 * Decorator for v-model binding
 * @param config - Optional v-model configuration extending PropsConfig
 * @returns Property decorator
 */
function VModel(config?: VModelConfig): PropertyDecorator;

// Alias for VModel
const Model: typeof VModel;

interface VModelConfig extends PropsConfig {
  name?: string;
}

Usage Examples:

import { Component, VModel } from "vue-facing-decorator";

@Component({
  template: `
    <div>
      <input v-model="value" />
      <input v-model="customModel" />
    </div>
  `
})
class VModelComponent {
  // Basic v-model (uses 'modelValue' prop and 'update:modelValue' event)
  @VModel()
  value!: string;

  // Custom v-model name
  @VModel({ name: "customValue" })
  customModel!: string;

  // V-model with validation
  @VModel({
    type: String,
    validator: (value: string) => value.length <= 100
  })
  limitedText!: string;

  // V-model with default
  @VModel({
    type: Number,
    default: 0,
    name: "count"
  })
  counter!: number;
}

// Usage in parent component:
// <VModelComponent v-model="parentValue" v-model:customValue="customValue" />

Vanilla Decorator

Decorator to preserve original class properties without transformation.

/**
 * Decorator to preserve original class properties without Vue transformation
 * @returns Property decorator
 */
function Vanilla(): PropertyDecorator;

Usage Examples:

import { Component, Vanilla, Setup } from "vue-facing-decorator";
import { ref } from "vue";

@Component
class VanillaComponent {
  // This will be transformed to reactive data
  @Setup(() => ref("reactive"))
  reactiveProperty!: string;

  // This will be preserved as-is, not transformed
  @Vanilla()
  staticProperty = "not reactive";

  // Vanilla method - preserved as class method
  @Vanilla()
  utilityMethod() {
    return "utility function";
  }

  // Regular method - becomes Vue component method
  componentMethod() {
    return this.reactiveProperty + " from component";
  }

  mounted() {
    console.log(this.staticProperty); // "not reactive"
    console.log(this.utilityMethod()); // "utility function"
    console.log(this.componentMethod()); // "reactive from component"
  }
}

Property Transformation Rules

The property decorators follow specific transformation rules:

  1. Setup: Properties become part of the component's setup function return
  2. Ref: Properties become accessors for template refs via $refs
  3. Prop: Properties become Vue component props with validation
  4. VModel: Properties become computed properties with getter/setter for two-way binding
  5. Vanilla: Properties are preserved exactly as defined in the class

Complete Example:

import { Component, Setup, Ref, Prop, VModel, Vanilla } from "vue-facing-decorator";
import { ref, computed } from "vue";

@Component({
  template: `
    <div>
      <h1>{{ title }}</h1>
      <input ref="textInput" v-model="inputValue" />
      <p>{{ computedMessage }}</p>
      <button @click="logStatic">Log Static</button>
    </div>
  `
})
class CompletePropertyExample {
  // Prop from parent
  @Prop({ type: String, required: true })
  title!: string;

  // Two-way binding
  @VModel()
  inputValue!: string;

  // Reactive computed property
  @Setup(() => computed(() => `You typed: ${this.inputValue}`))
  computedMessage!: string;

  // Template ref
  @Ref()
  textInput!: HTMLInputElement;

  // Static property (not reactive)
  @Vanilla()
  staticValue = "I don't change reactively";

  // Method
  logStatic() {
    console.log(this.staticValue);
    this.textInput.focus();
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-vue-facing-decorator

docs

advanced-features.md

core-components.md

index.md

method-lifecycle-decorators.md

property-decorators.md

tile.json