Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new HTMLDirective design #5826

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
af09c80
refactor: clean up array observer
EisenbergEffect Oct 15, 2021
dff2e70
refactor: modernize the splice code
EisenbergEffect Nov 4, 2021
ab76209
chore: set up SSR package (#5589)
nicholasrice Feb 11, 2022
1cf461d
feat: enable multiple instances of fast-element on a page at once (#5…
EisenbergEffect Mar 8, 2022
ab8e75d
refactor: extract polyfill and polyfill-like code to an optional modu…
EisenbergEffect Mar 17, 2022
c42b29d
feat: implement template renderer infrastructure (#5698)
nicholasrice Mar 28, 2022
d32ac1a
feat: new execution context design (#5800)
EisenbergEffect Apr 5, 2022
ce95dba
feat: new HTMLDirective API
EisenbergEffect Apr 8, 2022
9d883c3
feat: new directive registration/identification model
EisenbergEffect Apr 11, 2022
f466044
refactor: refine design/implementation of new directive aproach
EisenbergEffect Apr 11, 2022
fdfe90f
refactor: clean up comments, interfaces, types for directives/registries
EisenbergEffect Apr 11, 2022
4ddce3e
fix: update foundation to new APIs
EisenbergEffect Apr 11, 2022
40faed2
fix: update router to new directive APIs.
EisenbergEffect Apr 11, 2022
bff6135
fix: update ssr to new directive APIs
EisenbergEffect Apr 11, 2022
e35f948
refactor: clean up ssr switch to new directive APIs
EisenbergEffect Apr 11, 2022
bddabeb
fix: update React wrapper lib to use latest APIs
EisenbergEffect Apr 11, 2022
d73dda2
Change files
Apr 11, 2022
733ec32
fix: post rebase issues
EisenbergEffect Apr 12, 2022
0ebf260
fix: update reflectAttributes directive to new directive APIs
EisenbergEffect Apr 12, 2022
6d742da
test: add more tests to capture new html/directive aspect scenarios
EisenbergEffect Apr 12, 2022
358a5d9
Change files
Apr 12, 2022
b1e229f
chore: run prettier on foundation
EisenbergEffect Apr 12, 2022
7b79d71
Update packages/web-components/fast-ssr/src/template-parser/template-…
EisenbergEffect Apr 12, 2022
69a8e73
Update packages/web-components/fast-ssr/src/template-parser/template-…
EisenbergEffect Apr 12, 2022
8d739a9
Update packages/web-components/fast-foundation/src/directives/reflect…
EisenbergEffect Apr 12, 2022
70edb81
Update packages/web-components/fast-foundation/src/directives/reflect…
EisenbergEffect Apr 12, 2022
f31e66e
chore: cleanup tests after rebase
EisenbergEffect Apr 13, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "feat: new directive registration/identification model",
"packageName": "@microsoft/fast-element",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "fix: update foundation to new APIs",
"packageName": "@microsoft/fast-foundation",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "fix: update React wrapper lib to use latest APIs",
"packageName": "@microsoft/fast-react-wrapper",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "fix: update router to new directive APIs.",
"packageName": "@microsoft/fast-router",
"email": "[email protected]",
"dependentChangeType": "patch"
}
2 changes: 1 addition & 1 deletion packages/utilities/fast-react-wrapper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function getTagName<TElement, TEvents>(
) {
if (!config.name) {
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
const definition = FASTElementDefinition.forType(type)!;
const definition = FASTElementDefinition.getByType(type)!;

if (definition) {
config.name = definition.name;
Expand Down
129 changes: 90 additions & 39 deletions packages/web-components/fast-element/docs/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export interface Accessor {
setValue(source: any, value: any): void;
}

// @public
export type AddViewBehaviorFactory = (factory: ViewBehaviorFactory) => string;

// Warning: (ae-internal-missing-underscore) The name "AdoptedStyleSheetsStrategy" should be prefixed with an underscore because the declaration is marked as @internal
//
// @internal
Expand All @@ -25,23 +28,23 @@ export class AdoptedStyleSheetsStrategy implements StyleStrategy {
}

// @public
export enum Aspect {
attribute = 0,
booleanAttribute = 1,
content = 3,
event = 5,
property = 2,
tokenList = 4
}
export const Aspect: Readonly<{
none: number;
attribute: number;
booleanAttribute: number;
property: number;
content: number;
tokenList: number;
event: number;
assign(directive: Aspected, value: string): void;
}>;

// @public
export abstract class AspectedHTMLDirective extends HTMLDirective {
abstract readonly aspect: Aspect;
abstract readonly binding?: Binding;
abstract captureSource(source: string): void;
createPlaceholder: (index: number) => string;
abstract readonly source: string;
abstract readonly target: string;
export interface Aspected {
aspectType: number;
binding?: Binding;
sourceAspect: string;
targetAspect: string;
}

// @public
Expand Down Expand Up @@ -106,7 +109,7 @@ export interface BindingConfig<T = any> {
}

// @alpha (undocumented)
export type BindingMode = Record<Aspect, BindingType>;
export type BindingMode = Record<number, BindingType>;

// @public
export interface BindingObserver<TSource = any, TReturn = any, TParent = any> extends Notifier {
Expand Down Expand Up @@ -172,14 +175,14 @@ export interface ChildViewTemplate<TSource = any, TParent = any> {
// @public
export type CompilationStrategy = (
html: string | HTMLTemplateElement,
directives: readonly HTMLDirective[]) => HTMLTemplateCompilationResult;
factories: Record<string, ViewBehaviorFactory>) => HTMLTemplateCompilationResult;

// @public
export const Compiler: {
setHTMLPolicy(policy: TrustedTypesPolicy): void;
compile<TSource = any, TParent = any, TContext extends ExecutionContext<TParent> = ExecutionContext<TParent>>(html: string | HTMLTemplateElement, directives: ReadonlyArray<HTMLDirective>): HTMLTemplateCompilationResult<TSource, TParent, TContext>;
compile<TSource = any, TParent = any, TContext extends ExecutionContext<TParent> = ExecutionContext<TParent>>(html: string | HTMLTemplateElement, directives: Record<string, ViewBehaviorFactory>): HTMLTemplateCompilationResult<TSource, TParent, TContext>;
setDefaultStrategy(strategy: CompilationStrategy): void;
aggregate(parts: (string | HTMLDirective)[]): HTMLDirective;
aggregate(parts: (string | ViewBehaviorFactory)[]): ViewBehaviorFactory;
};

// @public
Expand Down Expand Up @@ -218,6 +221,11 @@ export class Controller<TElement extends HTMLElement = HTMLElement> extends Prop
readonly view: ElementView<TElement> | null;
}

// Warning: (ae-internal-missing-underscore) The name "createTypeRegistry" should be prefixed with an underscore because the declaration is marked as @internal
//
// @internal
export function createTypeRegistry<TDefinition extends TypeDefinition>(): TypeRegistry<TDefinition>;

// @public
export function css(strings: TemplateStringsArray, ...values: (ComposableStyles | CSSDirective)[]): ElementStyles;

Expand All @@ -231,7 +239,7 @@ export class CSSDirective {
export function cssPartial(strings: TemplateStringsArray, ...values: (ComposableStyles | CSSDirective)[]): CSSDirective;

// @public
export function customElement(nameOrDef: string | PartialFASTElementDefinition): (type: Function) => void;
export function customElement(nameOrDef: string | PartialFASTElementDefinition): (type: Constructable<HTMLElement>) => void;

// @public
export type DecoratorAttributeConfiguration = Omit<AttributeConfiguration, "property">;
Expand Down Expand Up @@ -329,17 +337,18 @@ export const FASTElement: (new () => HTMLElement & FASTElement) & {
new (): HTMLElement;
prototype: HTMLElement;
}>(BaseType: TBase): new () => InstanceType<TBase> & FASTElement;
define<TType extends Function>(type: TType, nameOrDef?: string | PartialFASTElementDefinition | undefined): TType;
define<TType extends Constructable<HTMLElement>>(type: TType, nameOrDef?: string | PartialFASTElementDefinition | undefined): TType;
};

// @public
export class FASTElementDefinition<TType extends Function = Function> {
export class FASTElementDefinition<TType extends Constructable<HTMLElement> = Constructable<HTMLElement>> {
constructor(type: TType, nameOrConfig?: PartialFASTElementDefinition | string);
readonly attributeLookup: Record<string, AttributeDefinition>;
readonly attributes: ReadonlyArray<AttributeDefinition>;
define(registry?: CustomElementRegistry): this;
readonly elementOptions?: ElementDefinitionOptions;
static readonly forType: <TType_1 extends Function>(key: TType_1) => FASTElementDefinition<Function> | undefined;
static readonly getByType: (key: Function) => FASTElementDefinition<Constructable<HTMLElement>> | undefined;
static readonly getForInstance: (object: any) => FASTElementDefinition<Constructable<HTMLElement>> | undefined;
get isDefined(): boolean;
readonly name: string;
readonly propertyLookup: Record<string, AttributeDefinition>;
Expand All @@ -366,11 +375,23 @@ export interface FASTGlobal {
export function html<TSource = any, TParent = any, TContext extends ExecutionContext<TParent> = ExecutionContext<TParent>>(strings: TemplateStringsArray, ...values: TemplateValue<TSource, TParent, TContext>[]): ViewTemplate<TSource, TParent>;

// @public
export abstract class HTMLDirective implements ViewBehaviorFactory {
abstract createBehavior(targets: ViewBehaviorTargets): Behavior | ViewBehavior;
abstract createPlaceholder(index: number): string;
targetId: string;
readonly uniqueId: string;
export interface HTMLDirective {
createHTML(add: AddViewBehaviorFactory): string;
}

// @public
export const HTMLDirective: Readonly<{
getForInstance: (object: any) => HTMLDirectiveDefinition<Constructable<HTMLDirective>> | undefined;
getByType: (key: Function) => HTMLDirectiveDefinition<Constructable<HTMLDirective>> | undefined;
define<TType extends Constructable<HTMLDirective>>(type: TType, options?: PartialHTMLDirectiveDefinition | undefined): TType;
}>;

// @public
export function htmlDirective(options?: PartialHTMLDirectiveDefinition): (type: Constructable<HTMLDirective>) => void;

// @public
export interface HTMLDirectiveDefinition<TType extends Constructable<HTMLDirective> = Constructable<HTMLDirective>> extends Required<PartialHTMLDirectiveDefinition> {
readonly type: TType;
}

// @public
Expand Down Expand Up @@ -418,9 +439,9 @@ export interface ItemViewTemplate<TSource = any, TParent = any> {

// @public
export const Markup: Readonly<{
interpolation: (index: number) => string;
attribute: (index: number) => string;
comment: (index: number) => string;
interpolation: (id: string) => string;
attribute: (id: string) => string;
comment: (id: string) => string;
}>;

// Warning: (ae-internal-missing-underscore) The name "Mutable" should be prefixed with an underscore because the declaration is marked as @internal
Expand Down Expand Up @@ -492,7 +513,7 @@ export const oneTime: BindingConfig<DefaultBindingOptions> & BindingConfigResolv

// @public
export const Parser: Readonly<{
parse(value: string, directives: readonly HTMLDirective[]): (string | HTMLDirective)[] | null;
parse(value: string, factories: Record<string, ViewBehaviorFactory>): (string | ViewBehaviorFactory)[] | null;
}>;

// @public
Expand All @@ -505,6 +526,11 @@ export interface PartialFASTElementDefinition {
readonly template?: ElementViewTemplate;
}

// @public
export interface PartialHTMLDirectiveDefinition {
aspected?: boolean;
}

// @public
export class PropertyChangeNotifier implements Notifier {
constructor(subject: any);
Expand Down Expand Up @@ -572,12 +598,14 @@ export class RepeatBehavior<TSource = any> implements Behavior, Subscriber {
}

// @public
export class RepeatDirective<TSource = any> extends HTMLDirective {
export class RepeatDirective<TSource = any> implements HTMLDirective, ViewBehaviorFactory {
constructor(itemsBinding: Binding, templateBinding: Binding<TSource, SyntheticViewTemplate>, options: RepeatOptions);
createBehavior(targets: ViewBehaviorTargets): RepeatBehavior<TSource>;
createPlaceholder: (index: number) => string;
createHTML(add: AddViewBehaviorFactory): string;
id: string;
// (undocumented)
readonly itemsBinding: Binding;
nodeId: string;
// (undocumented)
readonly options: RepeatOptions;
// (undocumented)
Expand Down Expand Up @@ -630,11 +658,13 @@ export class Splice {
}

// @public
export abstract class StatelessAttachedAttributeDirective<T> extends HTMLDirective implements ViewBehavior {
export abstract class StatelessAttachedAttributeDirective<T> implements HTMLDirective, ViewBehaviorFactory, ViewBehavior {
constructor(options: T);
abstract bind(source: any, context: ExecutionContext, targets: ViewBehaviorTargets): void;
createBehavior(targets: ViewBehaviorTargets): ViewBehavior;
createPlaceholder: (index: number) => string;
createHTML(add: AddViewBehaviorFactory): string;
id: string;
nodeId: string;
// (undocumented)
protected options: T;
abstract unbind(source: any, context: ExecutionContext, targets: ViewBehaviorTargets): void;
Expand Down Expand Up @@ -704,6 +734,26 @@ export type TrustedTypesPolicy = {
createHTML(html: string): string;
};

// Warning: (ae-internal-missing-underscore) The name "TypeDefinition" should be prefixed with an underscore because the declaration is marked as @internal
//
// @internal
export interface TypeDefinition {
// (undocumented)
type: Function;
}

// Warning: (ae-internal-missing-underscore) The name "TypeRegistry" should be prefixed with an underscore because the declaration is marked as @internal
//
// @internal
export interface TypeRegistry<TDefinition extends TypeDefinition> {
// (undocumented)
getByType(key: Function): TDefinition | undefined;
// (undocumented)
getForInstance(object: any): TDefinition | undefined;
// (undocumented)
register(definition: TDefinition): boolean;
}

// @public
export interface ValueConverter {
fromView(value: any): any;
Expand All @@ -728,7 +778,8 @@ export interface ViewBehavior<TSource = any, TParent = any> {
// @public
export interface ViewBehaviorFactory {
createBehavior(targets: ViewBehaviorTargets): Behavior | ViewBehavior;
targetId: string;
id: string;
nodeId: string;
}

// @public
Expand All @@ -738,9 +789,9 @@ export type ViewBehaviorTargets = {

// @public
export class ViewTemplate<TSource = any, TParent = any, TContext extends ExecutionContext<TParent> = ExecutionContext> implements ElementViewTemplate<TSource, TParent>, SyntheticViewTemplate<TSource, TParent, TContext> {
constructor(html: string | HTMLTemplateElement, directives: ReadonlyArray<HTMLDirective>);
constructor(html: string | HTMLTemplateElement, factories: Record<string, ViewBehaviorFactory>);
create(hostBindingTarget?: Element): HTMLView<TSource, TParent, TContext>;
readonly directives: ReadonlyArray<HTMLDirective>;
readonly factories: Record<string, ViewBehaviorFactory>;
readonly html: string | HTMLTemplateElement;
render(source: TSource, host: Node, hostBindingTarget?: Element, context?: TContext): HTMLView<TSource, TParent, TContext>;
type: any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ export class Controller<
return controller;
}

const definition = FASTElementDefinition.forType(element.constructor);
const definition = FASTElementDefinition.getForInstance(element);

if (definition === void 0) {
throw FAST.error(Message.missingElementDefinition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { FASTElementDefinition } from "./fast-definitions";
import { ElementStyles } from "../styles/element-styles";

describe("FASTElementDefinition", () => {
class MyElement {}
class MyElement extends HTMLElement {}

context("styles", () => {
it("can accept a string", () => {
Expand Down
Loading