aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields
diff options
context:
space:
mode:
Diffstat (limited to 'src/new_fields')
-rw-r--r--src/new_fields/Doc.ts109
-rw-r--r--src/new_fields/InkField.ts4
-rw-r--r--src/new_fields/RichTextField.ts10
-rw-r--r--src/new_fields/RichTextUtils.ts2
-rw-r--r--src/new_fields/SchemaHeaderField.ts11
-rw-r--r--src/new_fields/URLField.ts2
-rw-r--r--src/new_fields/documentSchemas.ts60
7 files changed, 130 insertions, 68 deletions
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 31173a5c1..4531fd5e0 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -378,8 +378,9 @@ export namespace Doc {
else list.splice(before ? ind : ind + 1, 0, doc);
}
}
+ return true;
}
- return true;
+ return false;
}
//
@@ -397,40 +398,6 @@ export namespace Doc {
return bounds;
}
- //
- // Resolves a reference to a field by returning 'doc' if no field extension is specified,
- // otherwise, it returns the extension document stored in doc.<fieldKey>_ext.
- // This mechanism allows any fields to be extended with an extension document that can
- // be used to capture field-specific metadata. For example, an image field can be extended
- // to store annotations, ink, and other data.
- //
- export function fieldExtensionDoc(doc: Doc, fieldKey: string, fieldExt: string = "yes") {
- return fieldExt && doc[fieldKey + "_ext"] instanceof Doc ? doc[fieldKey + "_ext"] as Doc : doc;
- }
-
- export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) {
- let docExtensionForField = new Doc(doc[Id] + fieldKey, true);
- docExtensionForField.title = fieldKey + ".ext";
- docExtensionForField.extendsDoc = doc; // this is used by search to map field matches on the extension doc back to the document it extends.
- docExtensionForField.type = DocumentType.EXTENSION;
- let proto: Doc | undefined = doc;
- while (proto && !Doc.IsPrototype(proto) && proto.proto) {
- proto = proto.proto;
- }
- (proto ? proto : doc)[fieldKey + "_ext"] = new PrefetchProxy(docExtensionForField);
- return docExtensionForField;
- }
-
- export function UpdateDocumentExtensionForField(doc: Doc, fieldKey: string, immediate: boolean = false) {
- let docExtensionForField = doc[fieldKey + "_ext"] as Doc;
- if (docExtensionForField === undefined) {
- if (immediate) CreateDocumentExtensionForField(doc, fieldKey);
- else setTimeout(() => CreateDocumentExtensionForField(doc, fieldKey), 0);
- } else if (doc instanceof Doc) { // backward compatibility -- add fields for docs that don't have them already
- docExtensionForField.extendsDoc === undefined && setTimeout(() => docExtensionForField.extendsDoc = doc, 0);
- docExtensionForField.type === undefined && setTimeout(() => docExtensionForField.type = DocumentType.EXTENSION, 0);
- }
- }
export function MakeTitled(title: string) {
let doc = new Doc();
doc.title = title;
@@ -453,7 +420,7 @@ export namespace Doc {
// for individual layout properties to be overridden in the expanded layout.
//
export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) {
- return BoolCast(layoutDoc.isTemplateField) && dataDoc && layoutDoc !== dataDoc && !(layoutDoc.layout instanceof Doc);
+ return BoolCast(layoutDoc.isTemplateField) && dataDoc && layoutDoc !== dataDoc && !(layoutDoc[StrCast(layoutDoc.layoutKey, "layout")] instanceof Doc);
}
//
@@ -469,15 +436,8 @@ export namespace Doc {
// ... which means we change the layout to be an expanded view of the template layout.
// This allows the view override the template's properties and be referenceable as its own document.
- let expandedTemplateLayout = dataDoc[templateLayoutDoc[Id]];
- if (expandedTemplateLayout instanceof Doc) {
- return expandedTemplateLayout;
- }
- if (expandedTemplateLayout instanceof Promise) {
- return undefined;
- }
let expandedLayoutFieldKey = "Layout[" + templateLayoutDoc[Id] + "]";
- expandedTemplateLayout = dataDoc[expandedLayoutFieldKey];
+ let expandedTemplateLayout = dataDoc[expandedLayoutFieldKey];
if (expandedTemplateLayout instanceof Doc) {
return expandedTemplateLayout;
}
@@ -492,13 +452,39 @@ export namespace Doc {
let layoutDoc: Doc | undefined = childDocLayout;
let resolvedDataDoc = !doc.isTemplateField && dataDoc !== doc && dataDoc ? Doc.GetDataDoc(dataDoc) : undefined;
if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) {
- Doc.UpdateDocumentExtensionForField(resolvedDataDoc, fieldKey);
- let fieldExtensionDoc = Doc.fieldExtensionDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title)), "dummy");
- layoutDoc = Doc.expandTemplateLayout(childDocLayout, fieldExtensionDoc !== resolvedDataDoc ? fieldExtensionDoc : undefined);
- } else layoutDoc = Doc.expandTemplateLayout(childDocLayout, resolvedDataDoc);
+ let extensionDoc = fieldExtensionDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title)));
+ layoutDoc = Doc.expandTemplateLayout(childDocLayout, extensionDoc !== resolvedDataDoc ? extensionDoc : undefined);
+ } else layoutDoc = childDocLayout;
return { layout: layoutDoc, data: resolvedDataDoc };
}
+ //
+ // Resolves a reference to a field by returning 'doc' if no field extension is specified,
+ // otherwise, it returns the extension document stored in doc.<fieldKey>_ext.
+ // This mechanism allows any fields to be extended with an extension document that can
+ // be used to capture field-specific metadata. For example, an image field can be extended
+ // to store annotations, ink, and other data.
+ //
+ export function fieldExtensionDoc(doc: Doc, fieldKey: string) {
+ let extension = doc[fieldKey + "_ext"] as Doc;
+ (extension === undefined) && setTimeout(() => CreateDocumentExtensionForField(doc, fieldKey), 0);
+ return extension ? extension : undefined;
+ }
+
+ export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) {
+ let docExtensionForField = new Doc(doc[Id] + fieldKey, true);
+ docExtensionForField.title = fieldKey + ".ext"; // courtesy field--- shouldn't be needed except maybe for debugging
+ docExtensionForField.extendsDoc = doc; // this is used by search to map field matches on the extension doc back to the document it extends.
+ docExtensionForField.extendsField = fieldKey; // this can be used by search to map matches on the extension doc back to the field that was extended.
+ docExtensionForField.type = DocumentType.EXTENSION;
+ let proto: Doc | undefined = doc;
+ while (proto && !Doc.IsPrototype(proto) && proto.proto) {
+ proto = proto.proto;
+ }
+ (proto ? proto : doc)[fieldKey + "_ext"] = new PrefetchProxy(docExtensionForField);
+ return docExtensionForField;
+ }
+
export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc {
Object.keys(doc).forEach(key => {
const field = ProxyField.WithoutProxy(() => doc[key]);
@@ -564,13 +550,13 @@ export namespace Doc {
let _applyCount: number = 0;
export function ApplyTemplate(templateDoc: Doc) {
if (templateDoc) {
- let applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), templateDoc.title + "(..." + _applyCount++ + ")");
+ let applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layoutCustom", templateDoc.title + "(..." + _applyCount++ + ")");
applied && (Doc.GetProto(applied).layout = applied.layout);
return applied;
}
return undefined;
}
- export function ApplyTemplateTo(templateDoc: Doc, target: Doc, titleTarget: string | undefined = undefined) {
+ export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined = undefined) {
if (!templateDoc) {
target.layout = undefined;
target.nativeWidth = undefined;
@@ -580,21 +566,14 @@ export namespace Doc {
return;
}
- let layoutCustom = Doc.MakeTitled("layoutCustom");
let layoutCustomLayout = Doc.MakeDelegate(templateDoc);
titleTarget && (Doc.GetProto(target).title = titleTarget);
- target.type = DocumentType.TEMPLATE;
- target.width = templateDoc.width;
- target.height = templateDoc.height;
- target.nativeWidth = templateDoc.nativeWidth ? templateDoc.nativeWidth : 0;
- target.nativeHeight = templateDoc.nativeHeight ? templateDoc.nativeHeight : 0;
- target.ignoreAspect = templateDoc.nativeWidth ? true : false;
+ Doc.GetProto(target).type = DocumentType.TEMPLATE;
target.onClick = templateDoc.onClick instanceof ObjectField && templateDoc.onClick[Copy]();
- target.layout = layoutCustomLayout;
- target.layoutNative = Cast(templateDoc.layoutNative, Doc) as Doc;
- target.layoutCustom = layoutCustom;
+ Doc.GetProto(target)[targetKey] = layoutCustomLayout;
+ target.layoutKey = targetKey;
return target;
}
@@ -616,6 +595,7 @@ export namespace Doc {
fieldTemplate.singleColumn = BoolCast(fieldTemplate.singleColumn);
fieldTemplate.nativeWidth = Cast(fieldTemplate.nativeWidth, "number");
fieldTemplate.nativeHeight = Cast(fieldTemplate.nativeHeight, "number");
+ fieldTemplate.type = fieldTemplate.type;
fieldTemplate.panX = 0;
fieldTemplate.panY = 0;
fieldTemplate.scale = 1;
@@ -666,9 +646,10 @@ export namespace Doc {
@observable BrushedDoc: ObservableMap<Doc, boolean> = new ObservableMap();
}
- // if this document's layout field contains a document (ie, a rendering template), then we will use that
- // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string.
- export function Layout(doc: Doc) { return doc.layout instanceof Doc ? doc.layout : doc; }
+ // the document containing the view layout information - will be the Document itself unless the Document has
+ // a layout field. In that case, all layout information comes from there unless overriden by Document
+ export function Layout(doc: Doc) { return Doc.LayoutField(doc) instanceof Doc ? doc[StrCast(doc.layoutKey, "layout")] as Doc : doc; }
+ export function LayoutField(doc: Doc) { return doc[StrCast(doc.layoutKey, "layout")]; }
const manager = new DocData();
export function UserDoc(): Doc { return manager._user_doc; }
export function SetUserDoc(doc: Doc) { manager._user_doc = doc; }
@@ -689,6 +670,8 @@ export namespace Doc {
return doc;
}
+
+ export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? "layoutKey1" : "layoutKey2"; }
export function linkFollowUnhighlight() {
Doc.UnhighlightAll();
document.removeEventListener("pointerdown", linkFollowUnhighlight);
diff --git a/src/new_fields/InkField.ts b/src/new_fields/InkField.ts
index e381d0218..d94834e91 100644
--- a/src/new_fields/InkField.ts
+++ b/src/new_fields/InkField.ts
@@ -8,7 +8,8 @@ export enum InkTool {
None,
Pen,
Highlighter,
- Eraser
+ Eraser,
+ Scrubber
}
export interface StrokeData {
@@ -17,6 +18,7 @@ export interface StrokeData {
width: string;
tool: InkTool;
displayTimecode: number;
+ creationTime: number;
}
export type InkData = Map<string, StrokeData>;
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
index f41ea0350..aa4908d51 100644
--- a/src/new_fields/RichTextField.ts
+++ b/src/new_fields/RichTextField.ts
@@ -13,17 +13,21 @@ export class RichTextField extends ObjectField {
@serializable(true)
readonly Data: string;
- constructor(data: string) {
+ @serializable(true)
+ readonly Text: string;
+
+ constructor(data: string, text: string = "") {
super();
this.Data = data;
+ this.Text = text;
}
[Copy]() {
- return new RichTextField(this.Data);
+ return new RichTextField(this.Data, this.Text);
}
[ToScriptString]() {
- return `new RichTextField("${this.Data}")`;
+ return `new RichTextField("${this.Data}", "${this.Text}")`;
}
[ToPlainText]() {
diff --git a/src/new_fields/RichTextUtils.ts b/src/new_fields/RichTextUtils.ts
index 601939ed2..c2cca859c 100644
--- a/src/new_fields/RichTextUtils.ts
+++ b/src/new_fields/RichTextUtils.ts
@@ -52,7 +52,7 @@ export namespace RichTextUtils {
};
export const Synthesize = (plainText: string, oldState?: RichTextField) => {
- return new RichTextField(ToProsemirrorState(plainText, oldState));
+ return new RichTextField(ToProsemirrorState(plainText, oldState), plainText);
};
export const ToPlainText = (state: EditorState) => {
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index 92d0aec9a..42a8485ac 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -41,6 +41,17 @@ export const PastelSchemaPalette = new Map<string, string>([
export const RandomPastel = () => Array.from(PastelSchemaPalette.values())[Math.floor(Math.random() * PastelSchemaPalette.size)];
+export const DarkPastelSchemaPalette = new Map<string, string>([
+ ["pink2", "#c932b0"],
+ ["purple4", "#913ad6"],
+ ["bluegreen1", "#3978ed"],
+ ["bluegreen7", "#2adb3e"],
+ ["bluegreen5", "#21b0eb"],
+ ["yellow4", "#edcc0c"],
+ ["red2", "#eb3636"],
+ ["orange1", "#f2740f"],
+]);
+
@scriptingGlobal
@Deserializable("schemaheader")
export class SchemaHeaderField extends ObjectField {
diff --git a/src/new_fields/URLField.ts b/src/new_fields/URLField.ts
index b9ad96450..35ef6dd02 100644
--- a/src/new_fields/URLField.ts
+++ b/src/new_fields/URLField.ts
@@ -38,6 +38,8 @@ export abstract class URLField extends ObjectField {
}
}
+export const nullAudio = "https://actions.google.com/sounds/v1/alarms/beep_short.ogg";
+
@scriptingGlobal @Deserializable("audio") export class AudioField extends URLField { }
@scriptingGlobal @Deserializable("image") export class ImageField extends URLField { }
@scriptingGlobal @Deserializable("video") export class VideoField extends URLField { }
diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts
new file mode 100644
index 000000000..fa47374f1
--- /dev/null
+++ b/src/new_fields/documentSchemas.ts
@@ -0,0 +1,60 @@
+import { makeInterface, createSchema, listSpec } from "./Schema";
+import { ScriptField } from "./ScriptField";
+import { Doc } from "./Doc";
+import { DateField } from "./DateField";
+
+export const documentSchema = createSchema({
+ layout: "string", // this is the native layout string for the document. templates can be added using other fields and setting layoutKey below (see layoutCustom as an example)
+ layoutKey: "string", // holds the field key for the field that actually holds the current lyoat
+ layoutCustom: Doc, // used to hold a custom layout (there's nothing special about this field .. any field could hold a custom layout that can be selected by setting 'layoutKey')
+ title: "string", // document title (can be on either data document or layout)
+ nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set
+ nativeHeight: "number", // "
+ width: "number", // width of document in its container's coordinate system
+ height: "number", // "
+ color: "string", // foreground color of document
+ backgroundColor: "string", // background color of document
+ opacity: "number", // opacity of document
+ creationDate: DateField, // when the document was created
+ links: listSpec(Doc), // computed (readonly) list of links associated with this document
+ dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy")
+ removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped
+ onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop)
+ onDragStart: ScriptField, // script to run when document is dragged (without being selected). the script should return the Doc to be dropped.
+ dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document.
+ ignoreAspect: "boolean", // whether aspect ratio should be ignored when laying out or manipulating the document
+ autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents
+ isTemplateField: "boolean", // whether this document acts as a template layout for describing how other documents should be displayed
+ isBackground: "boolean", // whether document is a background element and ignores input events (can only selet with marquee)
+ type: "string", // enumerated type of document
+ currentTimecode: "number", // current play back time of a temporal document (video / audio)
+ summarizedDocs: listSpec(Doc), // documents that are summarized by this document (and which will typically be opened by clicking this document)
+ maximizedDocs: listSpec(Doc), // documents to maximize when clicking this document (generally this document will be an icon)
+ maximizeLocation: "string", // flag for where to place content when following a click interaction (e.g., onRight, inPlace, inTab)
+ lockedPosition: "boolean", // whether the document can be moved (dragged)
+ lockedTransform: "boolean", // whether the document can be panned/zoomed
+ inOverlay: "boolean", // whether the document is rendered in an OverlayView which handles selection/dragging differently
+ borderRounding: "string", // border radius rounding of document
+ searchFields: "string", // the search fields to display when this document matches a search in its metadata
+ heading: "number", // the logical layout 'heading' of this document (used by rule provider to stylize h1 header elements, from h2, etc)
+ showCaption: "string", // whether editable caption text is overlayed at the bottom of the document
+ showTitle: "string", // whether an editable title banner is displayed at tht top of the document
+ isButton: "boolean", // whether document functions as a button (overiding native interactions of its content)
+ ignoreClick: "boolean", // whether documents ignores input clicks (but does not ignore manipulation and other events)
+ isAnimating: "boolean", // whether the document is in the midst of animating between two layouts (used by icons to de/iconify documents).
+ animateToDimensions: listSpec("number"), // layout information about the target rectangle a document is animating towards
+ scrollToLinkID: "string", // id of link being traversed. allows this doc to scroll/highlight/etc its link anchor. scrollToLinkID should be set to undefined by this doc after it sets up its scroll,etc.
+});
+
+export const positionSchema = createSchema({
+ zIndex: "number",
+ x: "number",
+ y: "number",
+ z: "number",
+});
+
+export type Document = makeInterface<[typeof documentSchema]>;
+export const Document = makeInterface(documentSchema);
+
+export type PositionDocument = makeInterface<[typeof documentSchema, typeof positionSchema]>;
+export const PositionDocument = makeInterface(documentSchema, positionSchema);